在没有依赖注入的情况下手动实例化多个 DbContext

Instantiate multiple DbContext manually without dependency injection

我想创建一个 ASP.Net 核心网络服务,它将 select 来自一个 SQL 服务器数据库的行并将它们插入 X SQL 服务器数据库.所有数据库都具有相同的结构(相同的模型)。

我不想注入 DbContext,因为我不知道我必须使用多少上下文,而且很难维护。

是否可以在控制器或管理器中手动创建 DbContext,例如:

MyContextClass dbContext = new MyContextClass("myConnectionString");

谢谢

是的,可以只创建一个新的 DbContext。 但是,当使用 DI 时,您应该编写并注入类似 DbContextFactory class 的内容,您可以使用它来创建新的上下文,并且它本身会从您的配置中获取 DbContextOptions

public class ContextFactory<TContext>
    where TContext : DbContext
{
    private readonly Func<TContext> _createContext;

    public ContextFactory(Func<TContext> createContext)
    {
        _createContext = createContext ?? throw new ArgumentNullException(nameof(createContext));
    }

    TContext CreateForRead()
    {
        var context = Create();

        context.ChangeTracker.AutoDetectChangesEnabled = false;
        context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;

        return context;
    }

    TContext CreateForWrite() => Create();

    private TContext Create()
    {
        var context = _createContext();
        if (context == null)
            throw new NullReferenceException($"{nameof(_createContext)} must not return null.");

        return context;
    }
}

为了方便使用,创建一个扩展 class:

public static class ServiceCollectionDataExtensions
{
    public static void AddDatabase<TDbContext>(this IServiceCollection services, string connectionString)
        where TDbContext : DbContext
    {
        if (services == null)
            throw new ArgumentNullException(nameof(services));

        if (string.IsNullOrEmpty(connectionString))
            throw new ArgumentNullException(nameof(connectionString));

        services.AddDbContext<TDbContext>(c => c.UseSqlServer(connectionString), ServiceLifetime.Transient);
        services.AddScoped(provider => new ContextFactory<TDbContext>(() => ActivatorUtilities.CreateInstance<TDbContext>(provider, provider.GetRequiredService<DbContextOptions<TDbContext>>())));
    }
}

然后在您的 public void ConfigureServices(IServiceCollection services) 中添加您配置中的连接字符串:

services.AddDatabase<MyDbContext>(Configuration.GetConnectionString("MyDatabase"));