应使用AddDbContextFactory而非AddDbContext的场景是:需运行时动态创建多个独立DbContext实例(如多租户、按参数切换连接字符串)或手动控制上下文生命周期(如后台任务中短时使用后立即释放),此时工厂提供显式创建能力,而AddDbContext适用于常规Scoped生命周期管理的Web请求场景。

什么时候该用 AddDbContextFactory 而不是 AddDbContext
当你需要在运行时动态创建多个独立的 DbContext 实例(比如按租户、按请求参数、或按数据库连接字符串切换),或者需要手动控制上下文生命周期(例如在后台任务中短时使用后立即释放),AddDbContextFactory 是更合适的选择。它不注册 DbContext 本身,而是注册一个工厂 IDbContextFactory,由你显式调用 CreateDbContext() 来获取新实例。
而 AddDbContext 是常规做法:它把 DbContext 当作服务注册进 DI 容器,默认按作用域(Scoped)生命周期管理,每次从同一个作用域(如一个 HTTP 请求)内解析出的都是同一个实例——这适合大多数 Web API 或 MVC 场景,但隐含了共享状态风险,且无法按需构造不同配置的上下文。
AddDbContextFactory 的典型使用场景和注意事项
常见于多租户系统、ETL 批处理、或需要并行操作多个数据库的后台服务。它默认注册为 Singleton,工厂本身是线程安全的,但生成的每个 DbContext 实例仍是短生存期、不可共享的。
- 必须手动调用
factory.CreateDbContext(),不能直接注入MyDbContext - 生成的
DbContext不参与当前作用域的自动释放,需确保用using或显式Dispose() - 若在 ASP.NET Core 请求处理中混用,容易因忘记释放导致连接泄漏
- 不支持 EF Core 的变更跟踪器跨实例共享,每个上下文都是完全隔离的
配置方式差异:连接字符串和选项如何传入
AddDbContext 通常在注册时通过 options => options.UseSqlServer(...) 固定配置;而 AddDbContextFactory 支持两种方式:
- 注册时传入固定配置(同上),所有工厂创建的上下文共用同一套选项
- 注册时不指定连接字符串,改用
factory.CreateDbContext(new[] { "Server=..." })动态传参(需自定义DbContextOptionsBuilder构建逻辑)
后者更灵活,但需重写 OnConfiguring 或提供自定义 IDbContextFactory 实现,EF Core 原生工厂不直接支持运行时切换连接字符串——得靠包装一层逻辑。
2013年07月06日 V1.60 升级包更新方式:admin文件夹改成你后台目录名,然后补丁包里的所有文件覆盖进去。1.[新增]后台引导页加入非IE浏览器提示,后台部分功能在非IE浏览器下可能没法使用2.[改进]淘客商品管理 首页 列表页 内容页 的下拉项加入颜色来区别不同项3.[改进]后台新增/修改淘客商品,增加淘宝字样的图标和天猫字样图标改成天猫logo图标4.[改进]为统一名称,“分类”改
性能与内存影响:别以为工厂就一定“更轻量”
工厂本身开销小,但每次调用 CreateDbContext() 都会新建整个 DbContext 实例及其依赖(如 ChangeTracker、Database 等),比复用作用域内已存在的上下文成本更高。如果只是想避免“单个请求里多次注入上下文”,用 AddDbContext + ServiceLifetime.Scoped 更高效;只有明确需要“每个操作独占上下文”时,才值得用工厂。
另外,若误在循环里高频调用 CreateDbContext() 却没及时 Dispose(),会快速耗尽数据库连接池——这是最常被忽略的实际问题。
services.AddDbContextFactory(options => options.UseSqlServer(connectionString) .EnableSensitiveDataLogging());
工厂注册之后,用的时候得这样:
public class Worker : BackgroundService
{
private readonly IDbContextFactory _factory;
public Worker(IDbContextFactory factory) => _factory = factory;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await using var context = _factory.CreateDbContext(); // 必须 using
var count = await context.Users.CountAsync(stoppingToken);
}
}
真正难的不是怎么写这行 _factory.CreateDbContext(),而是判断清楚:你到底需不需要这个“每次都新建”的行为——多数时候,你并不需要。









