891 字
4 分钟
深入浅出 EF Core 的 CRUD 操作(增删改查)
Entity Framework Core (EF Core) 作为 .NET 开发者最常用的 ORM 框架,其核心魅力在于将复杂的 SQL 操作抽象为对内存中“实体对象”的操作。本文将带大家深入了解如何执行高效的增删改查(CRUD),并剖析其底层的状态管理机制。
一、 EF Core 核心:实体状态机
在深入操作前,必须理解 EF Core 是如何感知数据变化的。每一个被 DbContext 加载的实体都有一个 EntityState。
- Detached:对象已创建,但尚未被 DbContext 跟踪。
- Added:对象在内存中是新的,数据库中尚不存在,调用
SaveChanges后将执行INSERT。 - Unchanged:对象与数据库一致,无需操作。
- Modified:对象属性被修改,调用
SaveChanges后将执行UPDATE。 - Deleted:对象被标记删除,调用
SaveChanges后将执行DELETE。
二、 数据新增操作 (Create)
使用 EF Core 插入数据时,推荐始终使用异步方法以提高系统吞吐量。
public async Task InsertAsync(){ using var context = new MyDbContext();
// 1. 业务逻辑判断 if (await context.TestTables.AnyAsync(p => p.Id == 1)) return;
// 2. 构造实体(此时状态为 Detached) var newEntity = new TestTable { Name = "新数据条目" };
// 3. 将状态标记为 Added await context.TestTables.AddAsync(newEntity);
// 4. 持久化(将内存变更转换为 SQL 事务执行) await context.SaveChangesAsync();}⚡ 避坑指南: > * 不要在方法签名中使用
async void(除非是事件处理),应使用async Task。
AddAsync仅在特殊场景(如使用某些 HiLo 自增序列)才真正需要异步。对于大多数情况,直接使用context.Add()也是可以的,因为它只操作内存。
三、 数据查询操作 (Read)
EF Core 提供了跟踪查询(默认)与非跟踪查询。
1. 跟踪查询 (Tracking)
默认情况下,EF Core 会在“快照”中记录查询到的实体。
var entities = await context.TestTables.ToListAsync();2. 非跟踪查询 (No-Tracking)
如果你只是展示数据,不打算修改,必须使用 AsNoTracking()。它能显著降低内存开销并提升查询速度,因为它跳过了状态跟踪逻辑。
var readOnlyList = await context.TestTables .AsNoTracking() .Where(p => p.Id > 10) .ToListAsync();四、 数据更新操作 (Update)
EF Core 的更新是基于“变化检测”的。
public async Task UpdateAsync(int id){ using var context = new MyDbContext();
// 1. 先追踪:从数据库获取原始数据 var entity = await context.TestTables.FindAsync(id);
if (entity != null) { // 2. 修改属性:EF Core 会自动将状态改为 Modified entity.Name = "更新后的名称";
// 3. 提交:仅会更新发生变化的列 await context.SaveChangesAsync(); }}💡 原理小贴士:当调用
SaveChangesAsync时,EF Core 会对比当前实体与查询时的“初始快照”,只针对有差异的字段生成UPDATE语句。
五、 数据删除操作 (Delete)
1. 常规删除(查 -> 删)
var entity = await context.TestTables.FindAsync(id);if (entity != null){ context.TestTables.Remove(entity); await context.SaveChangesAsync();}2. 高级技巧:无查询删除(仅通过主键)
如果你已知 ID,且不想额外消耗一次数据库查询请求,可以伪造一个“已附加”的对象:
var entity = new TestTable { Id = 1 }; // 仅需主键context.Entry(entity).State = EntityState.Deleted; // 直接标记状态await context.SaveChangesAsync();六、 总结与最佳实践
为了写出高性能、可维护的 EF Core 代码,请参考以下建议:
| 操作 | 最佳实践 |
|---|---|
| 查询 | 纯展示页面务必带上 .AsNoTracking()。 |
| 性能 | 批量操作(如一次增删上千条)应考虑 ExecuteUpdateAsync 或 ExecuteDeleteAsync(EF Core 7.0+ 引入)。 |
| 事务 | SaveChangesAsync 默认带有事务。如需跨 Context 事务,请使用 IDbContextTransaction。 |
| 异步 | 始终优先使用 ToListAsync、FirstOrDefaultAsync 等异步扩展方法。 |
深入浅出 EF Core 的 CRUD 操作(增删改查)
https://sw.rscclub.website/posts/efcrud/