当前位置: 首页 > news >正文

02020506 EF Core高级06-EF Core批量删除更新插入、全局筛选器、软删除、全局筛选的性能问题

02020506 EF Core高级06-EF Core批量删除&更新&插入、全局筛选器、软删除、全局筛选的性能问题

1. EF Core如何批量删除、更新、插入(视频3-36)

1.1 EF Core中插入数据(单条)
1、EF Core中不支持高效的删除、更新、插入数据,都是逐条操作。AddRange、DeleteRange等。
2、理想的:Delete from T_Books where Price>33
3、看看ctx.RemoveRange(ctx.Books.Where(b=> b.Price > 33))、 AddRange、批量更新等内部是怎么实现的。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// EF Core插入数据形式1
using (MyDbContext ctx = new MyDbContext())
{Article a01 = new Article { Message = "abc", Price = 10, Title = "ABC" };Article a02 = new Article { Message = "abc", Price = 10, Title = "ABC" };Article a03 = new Article { Message = "abc", Price = 10, Title = "ABC" };ctx.Articles.Add(a01);ctx.Articles.Add(a02);ctx.Articles.Add(a03);
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// EF Core插入数据形式2
using (MyDbContext ctx = new MyDbContext())
{Article a01 = new Article { Message = "abc", Price = 10, Title = "ABC" };Article a02 = new Article { Message = "abc", Price = 10, Title = "ABC" };Article a03 = new Article { Message = "abc", Price = 10, Title = "ABC" };ctx.Articles.AddRange(a01, a02, a03);
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// EF Core插入数据形式3
using (MyDbContext ctx = new MyDbContext())
{Article a01 = new Article { Message = "abc", Price = 10, Title = "ABC" };Article a02 = new Article { Message = "abc", Price = 10, Title = "ABC" };Article a03 = new Article { Message = "abc", Price = 10, Title = "ABC" };ctx.AddRange(a01, a02, a03);
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
总结:
1. 上述三种写法在EF Core中对数据库的操作是一样的,但这还是属于EF Core中数据一条条的插入。
2. AddRange方法知识用了for循环一条条的插入,也并不是一次性插入多条数据。
3. 在数据库中还是执行了三条insert语句。如果插入一万条呢?那么会有一万条insert,这样会造成性能损失。
1.2 EF Core中删除数据(单条)
// EF Core删除数据形式1
using Dapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using System;
using System.Data.Common;
using System.Linq;
using System.Threading.Tasks;namespace OneToMany
{class Program{static async Task Main(string[] args){using (MyDbContext ctx = new MyDbContext()){foreach (var item in ctx.Articles.Where(a => a.Id > 20)){ctx.Remove(item);}ctx.SaveChanges();}Console.WriteLine();}}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
using Dapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using System;
using System.Data.Common;
using System.Linq;
using System.Threading.Tasks;namespace OneToMany
{class Program{static async Task Main(string[] args){using (MyDbContext ctx = new MyDbContext()){ctx.RemoveRange(ctx.Articles.Where(a => a.Id > 1));ctx.SaveChanges();}Console.WriteLine();}}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
总结:上述两种写法在EF Core中对数据库的操作是一样的,但这还是属于EF Core中数据一条条的删除。

2. 为啥不用原生SQL实现

2.1 使用原生SQL的缺点
1、原生SQL语句需要把表名、列名等硬编码到SQL语句中,不符合模型驱动、分层隔离等思想,程序员直接面对数据库表,无法利用EF Core强类型的特性,如果模型发生改变,必须手动变更SQL语句。
1.1 如update t set Price = Price + 1
1.2 如delete from t where Id > 10
2、无法利用EF Core强大的SQL翻译机制来屏蔽不同底层数据库的差异。
3、EF Core官方迟迟未支持的原因。
2.2 微软官方关于此处的探讨
  • https://github.com/dotnet/efcore/issues/795
2.3 老师的开源实现
1、Zack.EFCore.Batch
2、await ctx.DeleteRangeAsync<Book>(b => b.Price > n || b.AuthorName =="zack yang");
await ctx.BatchUpdate<Book>().Set(b => b.Price, b => b.Price + 3).Set(b => b.Title, b => s).Set(b =>b.AuthorName,b=>b.Title.Substring(3,2)+b.AuthorName.ToUpper()).Set(b => b.PubTime, b => DateTime.Now).Where(b => b.Id > n || b.AuthorName.StartsWith("Zack")).ExecuteAsync();
ctx.BulkInsert(books);
2.4 Zack.EFCore.Batch包使用
  • 以Zack.EFCore.Batch -version 1.4.6示例
  • 官方文档:https://github.com/yangzhongke/Zack.EFCore.Batch

3. EF Core全局查询筛选器(视频3-37)

3.1 全局查询筛选器概述
1、全局查询筛选器:EF Core 会自动将这个查询筛选器应用于涉及这个实体类型的所有 LINQ 查询。
2、场景:软删除、多租户。
3.2 什么是软删除
图片链接丢失
delete from t where Name = "张三" // 直接从数据库删除,无法恢复,属于硬删除。增加IsDeleted列,为true表示屏蔽,为false表示未屏蔽,这样可以追溯。
3.3 软删除的用法示例一
  • 在在02020503章4.5节基础上继续
1、builder.HasQueryFilter(b=>b.IsDeleted==false);
2、测试一下如下的代码,查看生成的SQL:
ctx.Books.Where(b=>b.Price>20).ToArray()
3、忽略:ctx.Books.IgnoreQueryFilters().Where(b => b.Title.Contains("o")).ToArray()
查看SQL
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Article.cs
using System.Collections.Generic;namespace OneToMany
{class Article // 文章{public long Id { get; set; }public string Title { get; set; }public string Message { get; set; }public List<Comment> Comments { get; set; } = new List<Comment>();public int Price { get; set; }public bool IsDeleted { get; set; } // 增加状态列}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 迁移数据库之前
Id	Title	Message	Price	
1	杨中科入选中科院	大新闻	30
577	ABC	abc	10
578	ABC	abc	10
579	ABC	abc	10
580	ABC	abc	10
581	ABC	abc	10
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 迁移数据库
PM> add-migration isdeleted
Build started...
Build succeeded.
The Entity Framework tools version '5.0.4' is older than that of the runtime '5.0.5'. Update the tools for the latest features and bug fixes.
To undo this action, use Remove-Migration.
PM> update-database
Build started...
Build succeeded.
The Entity Framework tools version '5.0.4' is older than that of the runtime '5.0.5'. Update the tools for the latest features and bug fixes.
Applying migration '20251006023435_isdeleted'.
Done.
PM> 
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 迁移数据库之后
Id	Title	Message	Price	IsDeleted
1	杨中科入选中科院	大新闻	30	0
577	ABC	abc	10	0
578	ABC	abc	10	0
579	ABC	abc	10	0
580	ABC	abc	10	0
581	ABC	abc	10	0
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
using System;
using System.Threading.Tasks;namespace OneToMany
{class Program{static async Task Main(string[] args){using (MyDbContext ctx = new MyDbContext()){foreach (var item in ctx.Articles){Console.WriteLine(item.Id + item.Price);}}Console.WriteLine();}}
}控制台输出:
31
587
588
589
590
591
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
using System;
using System.Linq;
using System.Threading.Tasks;namespace OneToMany
{class Program{static async Task Main(string[] args){using (MyDbContext ctx = new MyDbContext()){var a = ctx.Articles.Single(a => a.Id == 1);a.IsDeleted = true;ctx.SaveChanges();}Console.WriteLine();}}
}// 此时数据库状态:
Id	Title	Message	Price	IsDeleted
1	杨中科入选中科院	大新闻	30	1 // 状态已经更新
577	ABC	abc	10	0
578	ABC	abc	10	0
579	ABC	abc	10	0
580	ABC	abc	10	0
581	ABC	abc	10	0
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
using System;
using System.Linq;
using System.Threading.Tasks;namespace OneToMany
{class Program{static async Task Main(string[] args){using (MyDbContext ctx = new MyDbContext()){foreach (var item in ctx.Articles) // 查询所有{Console.WriteLine(item.Id + item.Price);}Console.WriteLine("********************");foreach (var item in ctx.Articles.Where(a => a.IsDeleted == false)) // 依据IsDeleted来查询{Console.WriteLine(item.Id + item.Price);}}Console.WriteLine();}}
}控制台输出:
31
587
588
589
590
591
********************
587
588
589
590
591// SQL语句1
SELECT [t].[Id], [t].[IsDeleted], [t].[Message], [t].[Price], [t].[Title]FROM [T_Articles] AS [t]********************
// SQL语句2
SELECT t.Id, t.IsDeleted, t.Message, t.Price, t.TitleFROM T_Articles AS tWHERE t.IsDeleted == CAST(0 AS bit)),说明:SQL语句2增加了IsDeleted过滤
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
总结:每一次都要使用IsDeleted比较麻烦,可以使用全局筛选器来实现。
3.4 软删除的用法示例二
// ArticleConfig.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;namespace OneToMany
{class ArticleConfig : IEntityTypeConfiguration<Article>{public void Configure(EntityTypeBuilder<Article> builder){builder.ToTable("T_Articles");builder.Property(a => a.Title).HasMaxLength(100).IsUnicode().IsRequired();builder.Property(a => a.Message).IsUnicode().IsRequired();builder.HasQueryFilter(a => a.IsDeleted == false); // 增加筛选}}
}
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 使用全局过滤器
using System;
using System.Linq;
using System.Threading.Tasks;namespace OneToMany
{class Program{static async Task Main(string[] args){using (MyDbContext ctx = new MyDbContext()){foreach (var item in ctx.Articles) // 查询所有,但是已经屏蔽了Id为1的数据项{Console.WriteLine(item.Id + item.Price);}}Console.WriteLine();}}
}控制台输出:
587
588
589
590
591// SQL语句
SELECT [t].[Id], [t].[IsDeleted], [t].[Message], [t].[Price], [t].[Title]FROM [T_Articles] AS [t]WHERE [t].[IsDeleted] <> CAST(1 AS bit)说明:自动增加了IsDeleted过滤。
3.5 软删除的用法示例三
// 忽略全局过滤器
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading.Tasks;namespace OneToMany
{class Program{static async Task Main(string[] args){using (MyDbContext ctx = new MyDbContext()){foreach (var item in ctx.Articles.IgnoreQueryFilters()) // 忽略全局过滤器{Console.WriteLine(item.Id + item.Price);}}Console.WriteLine();}}
}控制台输出:
31
587
588
589
590
591// 查看SQLSELECT [t].[Id], [t].[IsDeleted], [t].[Message], [t].[Price], [t].[Title]FROM [T_Articles] AS [t]说明:忽略了IsDeleted过滤。
3.6 全局筛选的性能问题
  • 可以通过索引或者其它方面的优化,遇到了再来解决。
  • 傻瓜化的功能代表开发的时候不用关心细节问题,但不代表开发人员不需要知道相关知识点。
  • 开发人员可以尽情享受傻瓜化的功能,但是遇到问题你要知道所以然。

结尾

书籍:ASP.NET Core技术内幕与项目实战

视频:https://www.bilibili.com/video/BV1pK41137He

著:杨中科

ISBN:978-7-115-58657-5

版次:第1版

发行:人民邮电出版社

※敬请购买正版书籍,侵删请联系85863947@qq.com※

※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※

http://www.zskr.cn/news/19128.html

相关文章:

  • 一种整理HTML和JS代码的方法
  • 元推理框架,是人类文明的《神农本草经》,源于自指自洽的觉悟与洗礼
  • 【程序员必看】MySQL数据类型全解析:选错类型性能直接掉80%!
  • 2025环氧地坪漆厂家推荐:常州新禾,品质保证施工无忧!
  • 2025家居ERP推荐:赛思软件助力企业高效管理!
  • 2025彩钢瓦保养优质厂家推荐,江苏承优建筑工程专业服务!
  • 2025磁力泵加工厂推荐中正化工,专业定制高效耐用产品!
  • 2025双氧水供应厂家推荐:苏州市岚昱化工品质卓越选择!
  • 2025上海保洁公司最新推荐榜:高效清洁与贴心服务的优质选择
  • 2025书包柜定做厂家推荐:杰尚家具专业定制,品质卓越!
  • 打不动十个
  • 2025拉伸器厂家最新推荐榜:专业制造与优质服务的行业佼佼者
  • 2025氧化镁供应厂家推荐:松辽镁业高纯度优质选择!
  • 2025硅藻土订制厂家口碑推荐:品质卓越与专业服务的双重保障
  • 2025数控滚齿机订做厂家推荐:吉莱特智能装备,精准高效品质
  • Agno - 轻量级Python多智能体系统框架
  • P10960 SUBSTRACT 个人题解
  • 2025新型千斤顶厂家推荐:柳州市联桥科技,品质卓越服务到位
  • 2025年PP鱼池优质厂家推荐:超众渔业机械,环保耐用首选!
  • 完整教程:MongoDB Ops Manager部署
  • 2025医疗器械微弧氧化优质厂家推荐,华源漆业技术领先服务到
  • 【网络协议】SSL与TLS的关系 - 教程
  • 2025年安全光栅厂家最新推荐榜:精准防护与高效性能的工业首
  • 2025七水硫酸锌实力厂家推荐:安通环保科技,品质卓越信赖之
  • 2025磁力泵厂家最新推荐榜:高效稳定与优质服务的首选指南
  • 2025智能防爆灯厂家最新推荐榜:安全高效与技术创新典范
  • 2025氢氧化镁供应厂家推荐:辽宁润辉新材料科技优质厂家首选
  • 2025黄金回收品牌最新推荐榜:高信誉与专业服务的首选厂家!
  • 「Java EE制作指南」用MyEclipse创建的EJB开发工具(一)
  • 中考_学科