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


    EF 6及以前的版本是默认支持延迟加载(Lazy Loading)的,早期的EF Core中并不支持,必须使用Include方法来支持导航属性的数据加载。
    当然在EF Core 2.1及之后版本中已经引入了延迟加载功能,详细实现原理可以查看官网(传送门)。
    下面记录一下,分别使用IncludeLazy Loading来支持导航属性的数据加载。

    Entity数据库实体

    简单的一个多对多关系,分别对应数据库中的3张表。学生和学校之间通过StuSchReg关联,相互之间可以通过导航属性获取数据。

    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; }
        [ForeignKey("StdId")]
        public virtual Student Student { get; set; }
    
        public int SchId { get; set; }
        [ForeignKey("SchId")]
        public virtual School School { get; set; }
    }
    

    通过导航属性获取数据

    数据查询需求:通过学校Id获取学校中所有学生的信息

    [HttpGet]
    [HttpPost]
    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);
        });
    }
    

    这种情况下school.Regs会报错(未将对象引用到实例),断点查看会发现值为null。
    解决方法
    1.通过Include直接加载导航属性
    将获取school的语句修改一下,可以正常获取到数据。

    var school = dbContext.School
        .Include(d => d.Regs)
            .ThenInclude(d => d.Student)
        .FirstOrDefault(d => d.Id == id);
    

    2.开启EF Core的延迟加载功能
    使用延迟加载的最简单方式是安装 Microsoft.EntityFrameworkCore.Proxies 包,并通过调用 UseLazyLoadingProxies 来启用。
    例如:在DbContext的OnConfiguring方法中启用

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseLazyLoadingProxies()
            .UseSqlServer(myConnectionString);
    }
    

    或在使用AddDbContext时启用

    services.AddDbContext<BloggingContext>(
        b => b.UseLazyLoadingProxies()
              .UseSqlServer(myConnectionString));
    

    EF Core会为可重写的任何导航属性(必须是 virtual 且在可被继承的类上)启用延迟加载。
    这时候还原为最开始的调用方式,也可以正常获取到导航属性的数据了。

    var school = dbContext.School.Find(id);
    
  • 相关阅读:
    设计模式之简单数据工厂
    Linux CPU affinity
    QT操作Excel(通过QAxObject使用了OLE,前提是本地安装了Excel)
    QT 4.2.2的安装(安装完还要再编译,注意设置Windows Path)
    你要看透的56条人生哲理(还可以)
    提升Delphi编程效率必须使用的快捷键(Delphi2007版本)
    Delphi中复制带有String的记录结构时不能使用Move之类的内存操作函数
    普林斯顿大学算法公开课(1)----介绍
    iOS7 初体验
    SQL Server 性能优化之——系统化方法提高性能
  • 原文地址:https://www.cnblogs.com/cplemom/p/11499527.html
Copyright © 2020-2023  润新知