当DbContext具有DbContextOptionsBuilder参数时如何使用使用块

时间:2019-02-28 10:48:23

标签: c# asp.net entity-framework asp.net-core

当我在Startup.cs文件中启动应用程序时,必须将来自我的appsettings文件的连接字符串传递给DbContext,如下所示:

services.AddDbContext<ManagementStudioDbContext>(options => options.UseSqlServer(Configuration["DatabaseConfiguration:ConnectionString"]));

在创建DbContext的ContextFactory类中,它将DbContextOptionsBuilder变量传递给DbContext,如下所示:

public ManagementStudioDbContext CreateDbContext(string[] args)
{
    //Debugger.Launch();
    IConfigurationRoot configuration = new ConfigurationBuilder()
    .SetBasePath(ConfigurationManager.GetBasePath(Environment.GetEnvironmentVariable("CENTRAL_APPLICATION_SETTINGS")))
    .AddJsonFile("mssettings.json")
    .Build();
    var builder = new DbContextOptionsBuilder<ManagementStudioDbContext>();
    builder.UseSqlServer(configuration["DatabaseConfiguration:ConnectionString"]);
    return new ManagementStudioDbContext(builder.Options);
}

这就是我声明DbContext的方式:

public ManagementStudioDbContext(DbContextOptions<ManagementStudioDbContext> options) : base(options)
{

}

但是,当我要使用using()块时,这是一个问题,因为我需要将类型选项的参数传递给它。我可以通过什么以便可以使用using()块?

1 个答案:

答案 0 :(得分:1)

简单来说,您不需要。将EF上下文与using一起使用从来没有被接受,但是现在所有东西都注入了依赖项,这简直是站不住脚的。如果需要上下文的副本,则需要将其注入到类的构造函数中:

public class Foo
{
    private readonly ManagementStudioDbContext _context;

    public Foo(ManagementStudioDbContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    ...
}

上下文是作用域的,因此,如果您在单例类型的对象中需要它,则必须利用service-locator反模式。将IServiceProvider插入您的类中,使其具有单例生命期,然后在需要上下文副本时将其注入:

using (var scope = provider.CreateScope())
{
    var context = scope.ServiceProvider.GetRequiredService<ManagementStudioDbContext>();
    // do something with context
}

它被称为反专利产品,因为您应该尽可能避免这样做。一般来说,对象不应与寿命比其自身有限的对象一起使用。