必须通过adddbcontext注册di容器,否则手动new会导致并发异常、连接池耗尽、事务失效;onconfiguring应留空,避免覆盖di配置;多dbcontext需隔离onmodelcreating配置并明确指定迁移上下文。

DbContext 必须通过 AddDbContext 注册进 DI 容器,否则线程安全、连接复用、事务一致性全都会出问题。
为什么不能 new DbContext() 手动实例化
手动 new AppDbContext() 会绕过 DI 生命周期管理,导致:
- 多个请求共用同一个实例 → 并发写入时抛
InvalidOperationException: A second operation started on this context before a previous operation completed - 连接未及时释放 → 连接池耗尽,后续请求卡在
Timeout expired - 无法参与 ASP.NET Core 的 Scoped 事务(比如
ITransactionScope或 EF 自带的BeginTransaction)
正确做法只有一种:builder.Services.AddDbContext<appdbcontext>(options => options.UseSqlServer(...))</appdbcontext>,且必须在 Program.cs 中注册。
OnConfiguring 和构造函数注入冲突怎么办
只要用了 AddDbContext,OnConfiguring 就该删掉或留空。它和 DI 注入的 DbContextOptions 是互斥的——后者优先级更高,一旦 OnConfiguring 里又调了 UseSqlServer,就会覆盖掉配置中心读取的连接字符串,上线后连错库。
常见错误写法:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// ❌ 错:硬编码连接串,且覆盖 DI 配置
optionsBuilder.UseSqlServer("Server=...;Database=Test;");
}
正确写法是构造函数接收 DbContextOptions<appdbcontext></appdbcontext> 并传给基类,OnConfiguring 什么也不做。
多 DbContext 共存时 OnModelCreating 怎么隔离
每个 DbContext 的 OnModelCreating 只能配自己 DbSet<t></t> 里的类型。比如 OrderDbContext 里写了 modelBuilder.Entity<user>()</user>,迁移时会报 The entity type 'User' was not found —— 因为 User 不在它的 DbSet 列表中。
复用实体类没问题,但映射逻辑必须分开:
- 订单上下文只配
modelBuilder.Entity<order>()</order>和LineItem - 用户上下文只配
modelBuilder.Entity<user>()</user>和Profile - 共享配置可抽成扩展方法,如
ApplyUserConfigurations(this ModelBuilder),但必须在各自OnModelCreating里显式调用
迁移命令总提示“Unable to create an object of type 'XDbContext'”
这不是缺包,而是 CLI 工具找不到上下文类型。EF Core CLI 默认只扫描启动项目(通常是 Web 项目),如果你把 DbContext 放在 Infrastructure 类库中,就得明确告诉它去哪儿找:
- 加
-c指定类型:dotnet ef migrations add Init -c OrderDbContext - 加
--project指向类库:dotnet ef migrations add Init -c OrderDbContext --project ./src/Orders.Infrastructure - 迁移文件夹也要隔离:
--output-dir Migrations/Orders,否则多个上下文的迁移会混在一起,database update时可能漏执行
最常被忽略的是:更新数据库也得指定上下文,dotnet ef database update -c ProductDbContext,不加 -c 就只跑默认那个,其他库的表压根不会建。











