• 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);
    
  • 相关阅读:
    《梦断代码》阅读笔记01
    linux c netcdf 安装
    Windows CE中的进程和线程
    VC做任务管理器涉及到的函数
    curl_easy_getinfo() -- 从 curl 句柄里获得附加信息
    libcurl programming
    动态内存申请函数选择(realloc、malloc 、alloca、 calloc)
    C++: byte和int的相互转化
    8位灰度图像BMP的保存
    BMP图像的结构及读写和灰度化
  • 原文地址:https://www.cnblogs.com/cplemom/p/11499527.html
Copyright © 2020-2023  润新知