1.使用DbContext
池
在Core Mvc中,如果使用 AddDbContextPool
方法,那么在控制器请求 DbContext
实例时,我们会首先检查池中有无可用的实例。 请求处理完成后,实例的任何状态都将被重置,并且实例本身会返回池中。 从概念上讲,此方法类似于 ADO.NET 连接池的运行原理,并具有节约 DbContext
实例初始化成本的优势。
eg:
services.AddDbContextPool<BloggingContext>( options => options.UseSqlServer(connectionString));
2.优先使用异步方法
EF Core 中提供了很多形如 xxxAsync
的异步方法,推荐使用这些方法提高吞吐量和性能,减少不必要的延时等待。
3.多活动结果集连接复用
多活动结果集 (MARS
) 是一项允许对单个连接执行多个批处理的功能。 在以前的版本中,在单个连接上一次只能执行一个批处理。 使用 MARS
执行多个批处理并不意味着同时执行操作。 在连接字符串中添加:MultipleActiveResultSets=True
即可启用 MARS
特性。
详细见:https://docs.microsoft.com/zh-cn/dotnet/framework/data/adonet/sql/enabling-multiple-active-result-sets
4.批处理语句
EFCore中有一个重大改进,就是批处理,比如向数据库中增加n条数据(n>3
),会组合成一次请求访问数据库(而在以前的EF中,不是批处理,增加几条,则会访问几次)。
注:操作数据条数 <=3
的时候,不会批处理,还是分多次请求,只有>3
,才会批处理。
PS:可以手动设置批处理的条数MaxBatchSize
,默认值很大。optionsBuilder.UseSqlServer("Server=localhost;Database=EFDB01;User ID=sa;Password=123456;", b => b.MaxBatchSize(10));
(1). 增加
//1.增加 (3条及以下不合并,3条以上合并)
for (int i = 0; i < 5; i++)
{
dbContext.Add(new T_UserInfor() { id = Guid.NewGuid().ToString("N"), userAge = i, addTime = DateTime.Now });
}
int count = dbContext.SaveChanges();
(2). 修改
//2.修改(3条及以下不合并,3条以上合并)
var list = dbContext.T_UserInfor.Take(5).ToList();
foreach (var item in list)
{
item.userSex = "男111";
}
int count2 = dbContext.SaveChanges();
(3). 混合操作
//3.插入、更新、删除的混合操作 (3条及以下不合并,3条以上合并)
var list3 = dbContext.T_UserInfor.Take(2).ToList();
//增加
for (int i = 0; i < 2; i++)
{
dbContext.Add(new T_UserInfor() { id = Guid.NewGuid().ToString("N"), userAge = i, addTime = DateTime.Now });
}
//更新
foreach (var item in list3)
{
item.userAge = 12;
}
//删除
dbContext.Entry(list3.Take(1).FirstOrDefault()).State = EntityState.Deleted;
int count3 = dbContext.SaveChanges();
5.关闭状态追踪
跟踪行为决定了 EF Core 是否将有关实体实例的快照信息保留在其更改跟踪器中。 如果已跟踪某个实体,则该实体中检测到的任何更改都会在 SaveChanges()
期间永久保存到数据库。当决定只查询数据,不更改数据时,非跟踪查询十分有用,非跟踪查询的执行会更快,因为无需为查询实体设置快照跟踪信息。 如果不需要更新从数据库中检索到的实体,则应优先使用非跟踪查询。
(1).单体查询关闭:AsNoTracking()
(2).整个上下文关闭:context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
6.关闭状态同步
当从数据库进行查询数据时,上下文便捕获了每个实体属性的快照(数据库值,原始值,当前值),当调用SaveChanges
时,在内部会自动调用 DetectChanges
方法,此方法将扫描上下文中所有实体,并比较当前属性值和存储在快照中的原始属性值,如果被找到的属性值发生了改变,此时EF将会与数据库进行交互,进行数据更新。会导致自动调用 DetectChanges
方法: Find、Local、Remove、Add、Update、Attach、SaveChanges
和Entry
等。 但是,自动同步状态会频繁调用,可手动关闭以上方法的自动同步,当数据都修改好后,一次性手动同步。
关闭:context.ChangeTracker.AutoDetectChangesEnabled = false;
开启:context.ChangeTracker.DetectChanges();
7.使用 EF.Functions.xxx
进行查询
(1).使用 EF.Functions.Like
进行模糊查询要比 StartsWith、Contains
和 EndsWith
方法生成的SQL语句性能更优。
A. Contains
语句,生成的sql为:
var data3 = dbContext.T_UserInfor.Where(u => u.userName.Contains("p")).ToList();
用的是charindex
B. EF.Functions.Like
语句生成的sql为:
var data1 = dbContext.T_UserInfor.Where(u => EF.Functions.Like(u.userName, "%p%")).ToList();
//或者
var data2 = (from p in dbContext.T_UserInfor
where EF.Functions.Like(p.userName, "%p%")
select p).ToList();
用的是Like
PS:在传统的.Net中,还有种用法 SqlMethods
,详见:https://www.cnblogs.com/yaopengfei/p/11805980.html
(2).还有EF.Functions.DateDiffDay (DateDiffHour、DateDiffMonth)
,求天、小时、月之间的数量
PS:在EF Core中StartsWith
、Contains
和EndsWith
模糊查询实际分别被解析成为Left、CharIndex
和Right
,而不是Like
,而EF.Functions.Like
会解析成Like
语句。
详见:https://www.cnblogs.com/tdfblog/p/entity-framework-core-like-query.html
8.DbFunctionAttribute
标量函数
EF Core 支持映射数据库中定义的函数,可以在 LINQ
查询中使用,该功能支持将数据库标量函数映射到方法存根,使其可用于 LINQ
查询并转换为 SQL。 在 DbContext
上声明静态方法,并使用 DbFunctionAttribute
对其批注.