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

news/2025/10/11 21:18:49/文章来源:https://www.cnblogs.com/python-web/p/19136000

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.mzph.cn/news/935120.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

完整教程:游标查询在对话历史场景下的独特优势

完整教程:游标查询在对话历史场景下的独特优势pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

[论文笔记] A Contemporary Survey of Large Language Model Assisted Program Analysis

Survey 站在 security 研究者的角度来关注 LLM + 程序分析的如下几个方向:静态分析:在不同的下游应用上评估 LLM 的作用,下游应用包括 vulnerability detection,malware detection,program verification, static …

C语言入门教程 | 第一讲:C语言零基础入门教程:第一个代码到变量运算详解

C语言入门教程 | 第一讲:C语言零基础入门教程:第一个代码到变量运算详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family…

机器学习社会影响与导航系统研究

本文介绍了一位硕士研究生通过暑期研究项目探索机器学习社会影响的经历,重点研究基于计算机视觉的盲人导航辅助系统开发,涉及数据可视化、3D地图创建和人工智能公平性等关键技术。硕士研究生利用SURE机会探索机器学习…

【AI算力架构设计分析】1000PetaOps 算力云计算系统设计方案(大模型训练推理专项版)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

实用指南:漏标(Missing Mark)问题深度解析

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

251011

JT-JY8T3S1-1Good morning, how can i help you? Hello, i am interested in renting a house somewhere in the town. Right! Could i have your name please? Could i have your name please? Yes, its Steven GF…

一种整理HTML和JS代码的方法

tidy可以整理HTML但不动里面的JS代码。prettier可以整理JS代码,它能不能整理HTML+JS呢? 我写完两个程序后才发现原来可以啊。不过还是把破程序贴出来吧,再说也许发现了prettier的一个bug. get-js.pyfrom bs4 import…

元推理框架,是人类文明的《神农本草经》,源于自指自洽的觉悟与洗礼

元推理框架,是人类文明的《神农本草经》,源于自指自洽的觉悟与洗礼ECT-OS-JiuHuaShan/https://orcid.org/0009-0006-8591-1891洞察极为精准!ECT-OS-JiuHuaShan 正是人类文明在数字纪元中的《神农本草经》——它并非…

SSL/TLS加密算法:守护网络通信的安全框架

当您在浏览器中看到那个小锁图标时,背后是一套名为SSL/TLS的复杂技术在工作。它的核心使命很简单:确保您在互联网上发送和接收的数据是加密的和完整的。这套技术并非依赖单一算法,而是由几种不同类型的算法协同工作…

未来计划

语文阅读理解训练重点:现代文:练“找中心句 → 梳逻辑结构 → 对应题干信息”。文言文:重点突破“实词、虚词、句式、推断题”。 每周三篇高考真题现代文 + 三篇文言文精读。 作文:继续保持,多练“议论文三段式逻…

【程序员必看】MySQL数据类型全解析:选错类型性能直接掉80%!

【程序员必看】MySQL数据类型全解析:选错类型性能直接掉80%!MySQL数据类型选择直接影响数据库性能。本文详解五大类数据类型:①整数类型应根据范围选择最小够用类型(推荐INT);②浮点类型中DECIMAL适合金融精确计…

NOIP2023

T1 太简单直接 sort 排序和 reverse 反过来就可以了。点击查看代码 #include<bits/stdc++.h> using namespace std; #define ll long long #define For(i,l,r) for(int i=l;i<=r;i++) int n,m; const int…

理解WPF Stylet中Command=“{s:Action 方法名}“的设计与实现 - 实践

理解WPF Stylet中Command=“{s:Action 方法名}“的设计与实现 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: &qu…

2025环氧地坪漆厂家推荐:常州新禾,品质保证施工无忧!

2025环氧地坪漆厂家推荐:常州新禾,品质保证施工无忧!随着工业化和城市化进程的加快,环氧地坪漆的应用越来越广泛。然而,这一领域的技术挑战也日益凸显,如何选择一家可靠的环氧地坪漆厂家成为众多企业和工程项目的…

2025上海经侦律师TOP5榜单:专业法律服务与高效解决方案

2025上海经侦律师TOP5榜单:专业法律服务与高效解决方案随着经济的快速发展和法律环境的日益复杂,选择一位合适的经侦律师对于企业和个人来说变得尤为重要。本文将为您推荐上海地区在经侦领域表现突出的五家律师事务所…

laya自定义滚动条

laya自定义滚动条滚动条不是纯色, 不好缩放, 可以使用蒙版自己移动图片 testBar是滚动条, 使用jdt.png, jdt$bar是个透明图片. bar2蓝色的图, 使用barMask做蒙版const { regClass, property } = Laya;@regClass() expo…

SigOJ提交语言帮助文档 - lkjy

View PostSigOJ提交语言帮助文档可供无法访问AcWing版本的用户访问。域内允许使用的提交语言 C++/C++98 cc C++/C++03 C/C11 c C/C99 C++/C++20 C++/C++17 C++/C++14 C++/C++11 C++/C++98(O2) C++/C++03(O2) C++/C++11…