DbContext 必须用 using 或依赖注入管理生命周期,Web 应用注册为 Scoped,控制台用 using;增删改后须调用 SaveChangesAsync() 才写入;查询避免过早 ToList();异步方法必须 await 调用。

DbContext 实例必须用 using 或依赖注入管理生命周期
EF Core 的 DbContext 不是线程安全的,且内部持有数据库连接、变更追踪器等资源。直接 new 一个长期复用,会导致内存泄漏、连接池耗尽或并发修改异常。
常见错误现象:InvalidOperationException: A second operation started on this context before a previous operation completed,或程序跑一段时间后变慢、报连接超时。
- Web 应用(如 ASP.NET Core):注册为
Scoped,通过构造函数注入 —— 这是最推荐方式 - 控制台或短期脚本:用
using包裹,确保Dispose()被调用 - 绝对不要在静态字段里存
DbContext实例,也不要在单例服务中注入DbContext
增删改必须显式调用 SaveChangesAsync() 才会真正写入数据库
EF Core 的所有操作(Add()、Remove()、Update())只是标记实体状态,不触发 SQL。很多人写了 context.Customers.Add(newCustomer) 就以为数据已插入,结果查不到 —— 因为漏了保存。
使用场景:批量插入时,可先 AddRange() 多个对象,再统一 await context.SaveChangesAsync(),比逐条提交更高效。
-
Add():适用于新实体(ID 为默认值,如 0 或 null),状态设为Added -
Remove():传入已跟踪或未跟踪实体均可;若传未跟踪实体,需先Attach()或用RemoveRange()配合主键查询 -
Update():慎用!它会把整个实体标记为Modified,导致所有字段被 UPDATE —— 即使你只改了一个属性 - 更安全的更新方式:
context.Entry(entity).Property(e => e.Name).IsModified = true
查询时避免 .ToList() 过早执行,尤其在分页或大数据量场景
IQueryable<t></t> 是延迟执行的表达式树,.ToList()、.ToArray()、foreach 枚举会立即触发 SQL 查询并加载全部结果到内存。在没加 Where() 或 Take() 前就 .ToList(),可能把百万行数据拉进内存。
典型错误:写 context.Orders.ToList().Where(o => o.Status == "Shipped") —— 全表查出再内存过滤,数据库索引完全失效。
- 分页必须用
Skip()+Take()在 IQueryable 阶段完成,如context.Orders.Where(...).Skip(20).Take(10) - 需要统计总数?用
CountAsync(),不是.ToList().Count - 调试时想看生成的 SQL:启用 EF 日志(
options.LogTo(Console.WriteLine)),或用ToQueryString()(EF Core 5+)
异步方法命名和调用必须成对,否则容易引发死锁或性能退化
EF Core 几乎所有 I/O 操作都有异步版本(SaveChangesAsync、FirstOrDefaultAsync、ToListAsync),但它们依赖底层 Task 调度。如果在同步上下文(如 ASP.NET Framework 或控件事件)中用 .Result 或 .Wait() 强制等待,极易死锁。
性能影响:同步阻塞会占用线程池线程,高并发下线程耗尽,响应延迟飙升。
- ASP.NET Core 中,Controller Action 必须声明为
async Task<iactionresult></iactionresult>,并用await调用 EF 异步方法 - 控制台程序 Main 方法(C# 7.1+)可用
async Task Main(),避免GetAwaiter().GetResult() - 不要混合:比如
await context.Users.FindAsync(id)正确,而context.Users.Find(id)是同步查找,绕过变更追踪且无法 await
EF Core 的坑多数不在语法,而在资源管理、执行时机和异步契约这些隐性约定上。写完一行 Add(),得立刻问自己:它什么时候真正进库?谁负责释放连接?当前线程能不能等?


















