ibcadmin 发表于 2019-9-12 16:25:43

EF Core 通过延迟加载获取导航属性数据

<p>EF 6及从前的版本是默认支持延长加载(<code>Lazy Loading</code>)的,早期的EF Core中并不支持,必须使用<code>Include</code>方法来支持导航属性的数据加载。<br />
当然在<strong>EF Core 2.1</strong>及之后版本中已经引入了延长加载功能,具体实现原理可以查察官网(传送门)。<br />
下面记载一下,分别使用<code>Include</code>和<code>Lazy Loading</code>来支持导航属性的数据加载。</p>
<h4 id="entity数据库实体">Entity数据库实体</h4>
<p>简单的一个多对多关系,分别对应数据库中的3张表。门生和学校之间通过StuSchReg关联,相互之间可以通过导航属性获取数据。</p>
<code>public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual IList<StuSchReg> Regs { get; set; }
}

public class School
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual IList<StuSchReg> Regs { get; set; }
}
public class StuSchReg
{
    public int Id { get; set; }
    public int StdId { get; set; }
   
    public virtual Student Student { get; set; }

    public int SchId { get; set; }
   
    public virtual School School { get; set; }
}</code>
<h4 id="通过导航属性获取数据">通过导航属性获取数据</h4>
<p>数据查询需求:通过学校Id获取学校中全部门生的信息</p>
<code>

public async Task<JsonResult> Test(int id)
{
    return await Task.Run(() =>
    {
      var school = dbContext.School.Find(id);
      var list = school.Regs.Select(d => new { d.Student.Id, d.Student.Name });
      return Success(list);
    });
}</code>
<p>这种情况下<code>school.Regs</code>会报错(未将对象引用到实例),断点查察会发现值为null。<br />
<strong>管理方法</strong>:<br />
1.通过<code>Include</code>直接加载导航属性<br />
将获取school的语句修改一下,可以正常获取到数据。</p>
<code>var school = dbContext.School
    .Include(d => d.Regs)
      .ThenInclude(d => d.Student)
    .FirstOrDefault(d => d.Id == id);</code>
<p>2.开启EF Core的延长加载功能<br />
使用延长加载的最简单方式是安装 Microsoft.EntityFrameworkCore.Proxies 包,并通过调用 UseLazyLoadingProxies 来启用。<br />
例如:在DbContext的<code>OnConfiguring</code>方法中启用</p>
<code>protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
      .UseLazyLoadingProxies()
      .UseSqlServer(myConnectionString);
}</code>
<p>或在使用<code>AddDbContext</code>时启用</p>
<code>services.AddDbContext<BloggingContext>(
    b => b.UseLazyLoadingProxies()
          .UseSqlServer(myConnectionString));</code>
<p>EF Core会为可重写的任何导航属性(必须是 virtual 且在可被继续的类上)启用延长加载。<br />
这时间还原为最开始的调用方式,也可以正常获取到导航属性的数据了。</p>
<code>var school = dbContext.School.Find(id);</code><br><br/><br/><br/><br/><br/>来源:<a href="https://www.cnblogs.com/cplemom/archive/2019/09/10/11499527.html" target="_blank">https://www.cnblogs.com/cplemom/archive/2019/09/10/11499527.html</a>
页: [1]
查看完整版本: EF Core 通过延迟加载获取导航属性数据