efcore的一些性能优化

news/2024/5/20 0:07:51 标签: linq, 数据库, c#, .netcore

一、AsNoTracking

EF Core 提供了一种称为自动跟踪的功能,它可以将查询到的实体跟踪在内存中,以便对它们进行更改直到提交到数据库。在查询实体时,EF Core 将引用添加到内部跟踪集合中,以便可以在修改时进行检测和持久化到数据库中。

using (var context = new MyContext())
{
    var blog = context.Blogs.First();
    blog.Url = "https://example.com/";
    context.SaveChanges();
}

在上述示例中,我们在从数据库中查询到 Blog 实体后,更改了它的 Url 属性。由于默认情况下 EF Core 启用了自动跟踪的功能,该更改将自动将被检测到,然后 EF Core 将调用 SaveChanges() 方法将更改提交到数据库中。

需要注意的是,在大型应用程序或查询中使用自动跟踪可能会导致性能问题,因此对于一些查询不需要用到自动跟踪的情况,我们可以通过手动禁用跟踪来优化查询性能。可以通过使用 .AsNoTracking() 方法来禁用自动跟踪的功能,这样查询到的实体将不会被跟踪。例如:

using (var context = new MyContext())
{
    var blogs = context.Blogs.AsNoTracking().ToList();
}

总之,自动跟踪是 EF Core 中一个非常有用的功能,使得对实体的更改能够被跟踪和持久化到数据库中。但是,在大型的查询和应用程序中,需要使用其它优化方法来提高性能,例如使用手动禁用跟踪和 LINQ 查询优化等技巧。

 

二、Include

当使用Include() 方法时,EF Core通过一条SQL 查询同时加载主实体和相关联实体,从而减少了数据库查询的次数。在查询时,EF Core 查询生成器会在LINQ查询时自动将包含Include() 方法的 Lambda 表达式转换为联接查询,从而将实体及其关联数据加载到内存中。

例如,以下代码可用于将文章及其相关作者信息加载到内存中:

var blogs = context.Blogs.Include(b => b.Author).ToList();

上述代码是通过使用 Include() 方法来加载相关的实体,从而避免了额外的数据库查询。

当我们查询 Blog 实体时,EF Core 会尝试将关联的 Author 实体也加载到内存中,这样我们就能够在一次查询中获得Blog及其相关的Author信息。在查询时,EF Core查询生成器会自动将包含Include()方法的Lambda表达式转换成一个或多个联接查询,以便将实体及其相关数据加载到内存中。

需要注意的是,如果实体对象非常复杂,包含大量的关系数据,可能会导致性能问题。在使用Include()时,请根据需要仅加载必要的数据。对于多对多关系的实体,可以使用以下方式进行贪婪加载:

context.Blogs.Include(blog => blog.Tags).ThenInclude(tag => tag.Posts)

上述代码会同时将标签和它们关联的文章数据在一次查询中都加载到内存中。

总之,Include() 是一个有用的 EF Core 查询方法,能够帮助我们减少数据库查询次数,提高应用程序性能。同时,我们需要注意贪婪加载(Eager Loading)的使用,避免加载不必要的数据,从而影响查询效率。

三、Any()

在 EF Core 中,使用 .Any(),.Count(),.FirstOrDefault() 都可以得出相同的结果,但是它们在 SQL 查询中的表现有所不同,因此性能也是不同的。

  1. .Any()

.Any() 方法只是检查是否存在符合给定条件的数据记录。当使用 .Any() 时,EF Core 会在数据库中生成一条 “EXISTS” 子句。这比执行 COUNT() 检查数据记录数更快,因为 EXISTS 子句只返回 true 或 false。在执行 COUNT() 时,查询需要检查每个记录,直到计算出总记录数。因此,使用 .Any() 通常比 .Count() 更快。

例如:

var hasBlogs = context.Blogs.Any();

上述代码使用 .Any() 方法来检查 Blogs 表中是否存在记录。EF Core 将生成以下类似的 SQL 语句:

SELECT CASE WHEN EXISTS(SELECT 1 from [Blogs]) THEN 1 ELSE 0 END
  1. .Count()

.Count() 方法计算符合给定条件的数据记录的总数。当使用 .Count() 时,EF Core 会在数据库中生成一条 “SELECT COUNT(*)” 子句。因为要计算总记录数,所以使用 .Count() 比 .Any() 更耗费资源,因此执行时更慢。

例如:

var countBlogs = context.Blogs.Count();

上述代码使用 .Count() 方法来获取 Blogs 表中的记录总数。EF Core 将生成以下类似的 SQL 语句:

SELECT COUNT(*) from [Blogs]
  1. .FirstOrDefault()

.FirstOrDefault() 方法返回符合给定条件的第一条或默认数据记录。当使用 .FirstOrDefault() 时,EF Core 会在数据库中生成一条 SELECT 查询语句,并在匹配数据记录时停止查询。因此,.FirstOrDefault() 的效率通常比 .Count() 更高,但比 .Any() 稍微慢一些。

例如:

var blog = context.Blogs.FirstOrDefault();

上述代码使用 .FirstOrDefault() 方法来获取 Blogs 表的第一条数据记录。EF Core 将生成以下类似的 SQL 语句:

SELECT TOP(1) * FROM [Blogs]

总之,.Any() 通常比 .Count() 更快,.FirstOrDefault() 的效率通常介于两者之间。当需要获取查询结果集合的详细信息时,可以使用 .Count(),当只需要知道结果集是否存在时,可以使用 .Any()。而 .FirstOrDefault() 通常用于获取数据集合中的第一个记录。

四、Find()

在 EF Core 中,Find() 和 FirstOrDefault() 方法都是用于从数据库中获取指定实体对象的方法,但它们的使用场景有所不同。

Find() 方法用于在指定的 DbSet<TEntity> 集合中查找实体,并根据主键的值将该实体直接从内存中获取。如果在内存中找不到该实体,则会从数据库中获取它。而 FirstOrDefault() 方法则在数据库中执行一条 SQL 查询,用于从集合中获取第一条记录或匹配指定条件的第一条记录。

因此,当要查询的实体对象已经存在于 DbContext 的 ChangeTracker 中时(通常是在前面的查询中读取过该实体数据,或者手工将该实体添加到 DbContext 的 ChangeTracker 中),使用 Find() 方法来获取数据的效率比使用 FirstOrDefault() 方法更高,因为它不需要额外的数据库查询操作。

而如果要在集合中查找符合指定条件的第一条记录,或者要返回数据集合中的第一条记录,则应该使用 FirstOrDefault() 方法。

需要注意的是,Find() 方法仅适用于透明的主键属性。对于复合主键、非透明主键、已定义计算属性或属性的值生成,不能使用 Find() 方法。

总之,Find() 和 FirstOrDefault() 方法的使用场景有所不同,根据场景选择合适的方法可以提高 EF Core 应用程序的性能。如果要查询的实体已经存在于 DbContext 的 ChangeTracker 中时,使用 Find() 方法的效率更高。否则,应该使用 FirstOrDefault() 方法进行查询。


http://www.niftyadmin.cn/n/340274.html

相关文章

IMX6ULL裸机篇之DDR3初始化

一. DDR3L初始化简介 I.MX6U-ALPHA 开发板上带有一个 256MB/512MB 的 DDR3 内存芯片&#xff0c;16 位宽&#xff0c;型号为 NT5CC128M16JR/MT5CC256M16EP&#xff0c;nanya 公司出品的&#xff0c;分为对应 256MB 和 512MB 容量。 我自己用的开发板上 DDR3L内存芯片型号为…

c++设计模式一:单例模式

使用场景&#xff1a;确保只有一个类对象存在&#xff0c;避免此类被多次实例化。 比如软件中有个按钮&#xff0c;按下后弹出一个对话框&#xff0c;对话框中要显示一大堆数据&#xff0c;这些数据需要从一个文件中读取出来&#xff0c;用户选择一种后窗口消失&#xff0c;再次…

自动生成测试用例_接口测试用例自动生成工具

前言 写用例之前&#xff0c;我们应该熟悉API的详细信息。建议使用抓包工具Charles或AnyProxy进行抓包。 har2case 我们先来了解一下另一个项目har2case 他的工作原理就是将当前主流的抓包工具和浏览器都支持将抓取得到的数据包导出为标准通用的 HAR 格式&#xff08;HTTP A…

【技术】《Netty》从零开始学netty源码(六十)之ByteToMessageDecoder

ByteToMessageDecoder 在Netty中用于拆包的解码器都继承了抽象类ByteToMessageDecoder&#xff0c;它的类结构如下&#xff1a; 从中可以看出它其实就是一个handler&#xff0c;只要添加到pipeline中channel每次读取数据的时候都会得到解析&#xff0c;它的数据结构如下&#…

什么是即时 AI ?有哪些应用场景

什么是即时 AI &#xff1f; 即时 AI 是全球首款通过自然语言描述&#xff0c;快速生成可编辑的 UI 设计稿的设计工具。 输入文字描述后&#xff0c;即可一次性生成4张 包含矢量图层和图标、支持二次编辑、分层结构清晰 UI 设计稿。 即时 AI 目前已面向全部用户免费开放&#…

【密码学复习】第七章 公钥加密体制(二)

RSA单向陷门函数及其应用 ElGamal单向陷门函数 1&#xff09;密钥生成 ① 选择一大素数p,选取Zp * 的生成元g ; ② 任选小于p的随机数x&#xff0c;计算y≡g x mod p; ③(y, g, p)为公开密钥&#xff0c; (x, g, p)为秘密密钥. 2&#xff09;加密&#xff1a;设待加密…

湖北棒球发展报告·棒球5号位

湖北棒球的发展报告与办法应该考虑以下几个因素&#xff1a; 1. 借助政策支持。湖北棒球要想发展&#xff0c;政策支持是必不可少的。政府需要提供足够的资金和政策支持&#xff0c;以帮助俱乐部提高运营能力和加强比赛的组织。获得政府的政策支持&#xff0c;可以促进湖北棒球…

uni-app之使用Vite.config.js配置文件的详细教程

uni-app 是一个基于 Vue.js 的跨平台开发框架&#xff0c;而 Vite 是一个快速的前端构建工具。结合使用 Uni-app 和 Vite 可以提高开发效率和构建速度。本文将详细介绍如何使用 Vite.config.js 配置文件来配置 Uni-app 项目。 1. 介绍 Vite.config.js 是 Vite 构建工具的配置…