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 //1.增加 (3条及以下不合并,3条以上合并) 2 for (int i = 0; i < 5; i++) 3 { 4 dbContext.Add(new T_UserInfor() { id = Guid.NewGuid().ToString("N"), userAge = i, addTime = DateTime.Now }); 5 } 6 int count = dbContext.SaveChanges();
(2). 修改
1 //2.修改(3条及以下不合并,3条以上合并) 2 var list = dbContext.T_UserInfor.Take(5).ToList(); 3 foreach (var item in list) 4 { 5 item.userSex = "男111"; 6 } 7 int count2 = dbContext.SaveChanges();
(3). 混合操作
1 //3.插入、更新、删除的混合操作 (3条及以下不合并,3条以上合并) 2 var list3 = dbContext.T_UserInfor.Take(2).ToList(); 3 //增加 4 for (int i = 0; i < 2; i++) 5 { 6 dbContext.Add(new T_UserInfor() { id = Guid.NewGuid().ToString("N"), userAge = i, addTime = DateTime.Now }); 7 } 8 //更新 9 foreach (var item in list3) 10 { 11 item.userAge = 12; 12 } 13 //删除 14 dbContext.Entry(list3.Take(1).FirstOrDefault()).State = EntityState.Deleted; 15 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 对其批注.
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。