智慧团建网站登录入口官网,网站页脚有什么作用,企业微信有哪些功能,互联网站的建设维护营销这是 EF Core 系列的第四篇文章#xff0c;上一篇文章讲述了 EF Core 中的实体迁移与数据播种。这篇文章盘点一下 EF Core 的几种数据查询方式#xff0c;内容较多分上下两篇。点击上方或后方蓝字#xff0c;阅读 EF Core 系列合集。简单查询在 EF Core 中#xff0c;每个查… 这是 EF Core 系列的第四篇文章上一篇文章讲述了 EF Core 中的实体迁移与数据播种。这篇文章盘点一下 EF Core 的几种数据查询方式内容较多分上下两篇。点击上方或后方蓝字阅读 EF Core 系列合集。简单查询在 EF Core 中每个查询都由三个主要部分组成通过 ApplicationContext 的 DbSet 属性连接到数据库使用一系列的 LINQ 或 EF Core 命令执行查询这是一个最简单的示例public void Run()
{var accounts _context.Accounts.Where(s s.Age 16).ToList();
}从这个查询中我们可以看到查询的三个主要部分「_context.Accounts」 是查询第一部分通过 DbSetAccount 属性访问数据库中的 Account 表。「Where(s s.Age 25)」 是查询的第二部分使用 LINQ 方法筛选需要的行。最后「ToList()」 方法用来来执行这个查询。需要注意的是当我们在 EF Core 中编写只读查询时可以添加 AsNoTracking 方法提高查询效率_context.Accounts.AsNoTracking()使用 AsNoTracking 方法时EF Core 不会跟踪加载实体的变化。关系型查询在 EF Core 查询导航属性表关联字段的方式有多种「贪婪加载」、「显式加载」和「懒惰加载」。贪婪加载贪婪加载也叫预先加载。所谓贪婪加载就是在查询结果中包含导航关系而这就需要明确的要求。比如这个示例中Account 拥有两个导航属性AccountDetails属性是一对一的导航关系AccountSubjects属性是一对多的导航关系。运行这个简单查询的结果如下可以发现控制台的结果中两个导航属性的值都是 Null。在 EF Core 中只有明确要求的情况下才会在结果中包含导航关系。这个简单查询中没有明确要求包含导航关系。如果使用贪婪加载可以让 EF Core 在查询结果中包含导航属性的值。贪婪加载通过使用 Include() 和 ThenInclude() 方法实现如下所示var accounts _context.Accounts.Include(e e.AccountSubjects).Where(s s.Age 16).ToList();Include 方法用来加载第一层导航关系如果想进一步加载导航关系呢比如 AccountSubjects 属性中有两个一对一导航分别是 Accout 属性和 Subject 属性如果我们想通过 AccountSubjects 导航属性进一步查询出 Subject 属性就可以这么做 var accounts _context.Accounts.Include(e e.AccountSubjects).ThenInclude(s s.Subject).Where(s s.Age 16).ToList();ThenInclude 方法用来进一步加载导航关系。该方法可以无限递进非关系深度如果关系不存在查询也不会失败只是不会返回任何东西。「贪婪加载的优点是以一种高效的方式查询了关系型数据使用了最少的数据库访问次数」「它的缺点是一次性加载了所有的数据即使我们不需要其中的某些数据。」显式加载所谓显式加载就是 EF Core 显式地将关系加载到已经加载的实体中。比如这个示例var account _context.Accounts.FirstOrDefault();_context.Entry(account).Collection(ss ss.AccountSubjects).Load();foreach (var accountSubject in account.AccountSubjects)
{_context.Entry(accountSubject).Reference(s s.Subject).Load();
}我们首先加载的是 Acount 实体然后通过 AccountSubjects 导航属性关联所有相关的子项。在这种情况下Acount 实体被称为主实体。Collection 方法可以把一个集合纳入主实体Reference 方法可以把单一的实体纳入主实体。Account 实体通过使用 Collection 方法包含了 AccountSubjec 集合。AccountSubject 实体通过使用 Reference 方法包含了 Subject 实体。使用显式加载时除了 Load 加载方法还可以使用查询方法它允许将查询应用到关系中var count _context.Entry(account).Collection(a a.AccountSubjects).Query().Count();var subjects _context.Entry(account).Collection(a a.AccountSubjects).Query().Select(s s.Subject).ToList();「显式加载的好处是只有当真正需要的时候我们才会在实体类上加载一个导航关系。」另一个好处是如果我们有复杂的业务逻辑那就可以分别加载导航关系。另外导航关系加载可以封装到一个方法、甚至是一个类中从而使代码更容易阅读和维护。不过这种方法的缺点是会产生更多的数据库查询次数来加载所有需要的关系会降低查询的效率。懒惰加载懒加载也叫延迟加载、按需加载它和贪婪加载相反顾名思义暂时不需要的数据就不加载而是推迟到使用它时再加载。延迟加载是一个比较重要的数据访问特性它可以有效地减少与数据源的交互。注意这里所指的交互不是指交互次数而是指交互的数据量。EF Core 中默认是不开启这个功能的因为在使用不当的情况下它会降低应用的性能。想要使用懒加载最简单的办法就是安装 Microsoft.EntityFrameworkCore.Proxies 库使用代理模式实现懒加载。在上下文类的配置方法中启用懒加载代理protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{optionsBuilder.UseLazyLoadingProxies();
}配置完成后EF Core 会为任何可以被重载的导航属性启用懒惰加载。需要注意的是这是一种全局配置所有的导航属性都必须使用 virtual 修饰否则会发生异常错误。不过这样一来的话所有的导航属性都默认启用了懒加载。除了使用代理模式还可以使用 EF Core 中的懒加载服务这种方式不需要用 virtual 修饰导航属性而且可以只针对特定实体进行懒加载。具体来看示例public class Account
{private readonly ILazyLoader _lazyLoader;public Account(ILazyLoader lazyLoader){_lazyLoader lazyLoader;}private ICollectionAccountSubject _accountSubjects;public ICollectionAccountSubject AccountSubjects{get _lazyLoader?.Load(this, ref _accountSubjects);set _accountSubjects value;}}使用构造函数注入的方式将 ILazyLoader 服务注入到实体类中然后修改需要开启懒加载的字段。需要注意的是滥用懒加载会造成性能上的问题。虽然懒加载只在需要读取关联数据的时候才进行加载但是如果在遍历中使用的话每次读取一条数据那么就会查询一次数据库增加了访问数据库的次数会导致数据库的压力增大。贪婪加载也一样会有性能上的问题因为一次性读取所有相关的数据有可能会导致部分数据在实际上用不到从而使查询数据的效率降低。所以我们应该清楚什么时候应该使用哪种加载方式如果在开发时不确定是否会需要相关联的数据那么可以选择懒加载待确定需要后再加载它。如果在开发时就可以预见需要一次性加载所有的数据而且需要包含导航关系的所有数据 那么使用贪婪加载是比较好的选择。更多精彩内容请关注我▼▼如果喜欢我的文章那么在看和转发是对我最大的支持戳下面蓝字阅读ASP.NET 6 中间件系列ASP.NET 最通俗易懂的依赖注入系列查缺补漏系统学习 EF Core 6 系列老子不亏是程序员的祖师爷不得不知的超精简 HTTP 协议推荐关注微信公众号码侠江湖 觉得不错点个在看再走哟
相关文章: