Entity FrameWork(简称 EF)以面向对象的方式操作数据库给开发人员带来了很大的便利性,但其性能问题从面世以来就一直就被广大的 .NET 生态开发技术人员所吐槽,然而,它真的那么不堪使用吗?试试下面这 6 个小技巧,瞬间极大提升 EF Core 性能:
-
AsNoTracking
在项目开发的时候,如果查询出来的对象不会被修改、删除等,那么在查询的时候,可以启用AsNoTracking,这样就能降低EF Core的资源占用
c#Book[] books = ctx.Books.AsNoTracking().Take(3).ToArray(); Book b1 = books[0]; b1.Title = "abc"; EntityEntry entry1 = ctx.Entry(b1); Console.WriteLine(entry1.State);
-
通过一条SQL语句高效更新实体类
c#Book b1 = new Book {Id=10}; b1.Title = "yzk"; var entry1 = ctx.Entry(b1); //直接创建实体对象 entry1.Property("Title").IsModified = true; //标记 Title 字段被修改 Console.WriteLine(entry1.DebugView.LongView); ctx.SaveChanges(); //只生成这个字段的更新的SQL语句
-
用一条SQL语句高效删除数据
c#Book b1 = new Book { Id = 28 }; ctx.Entry(b1).State = EntityState.Deleted; ctx.SaveChanges();
-
关于 Find 和 FindAsync 方法
Find 或者 FindAsync 方法(以下简称为Find)会先在上下文查找这个对象是否已经被跟踪,如果对象已经被跟踪,就直接返回被跟踪的对象,只有在本地没有找到这个对象时,EF Core 才去数据库查询,而 Single 方法则一直都是执行一次数据库查询。因此用 Find 方法有可能减少一次数据库查询,性能更好。但是如果在对象被跟踪之后,数据库中对应的数据已经被其他程序修改了,则 Find 方法可能会返回旧数据。
-
如何在 EF Core 中高效地删除、更新数据?
- 使用原生 SQL,但不太符合模型驱动、分层隔离等思想
- 使用其它开源库如 Zack.EFCore.Batch
-
全局查询筛选器
EF Core 支持在配置实体类的时候,为实体类设置全局查询筛选器,EF Core 会自动将全局查询筛选器应用于涉及这个实体类型的所有 LINQ 查询。这个功能常见的应用场景有 "软删除" 和 "多租户"
c#Fluent API配置全局查询筛选器: builder.HasQueryFilter(b=>b.IsDeleted==false) 忽略全局查询筛选器 ct x.Books.IgnoreQueryFilters().Where(b => b.Title.Contains("o")).ToArray();