如何在.NET Core中实现DbContextOptionsBuilder

时间:2019-03-14 14:32:04

标签: c# asp.net-core-2.0

我是ASP.Net Core的新手,我正在尝试实现ASP.NET Core DI。

我在Startup.cs的ConfigureServices方法中进行了如下配置

services.AddScoped<DbContext, AutomationDbContext>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddTransient<IUserService, UserService>();

在UserService构造函数中,我正在尝试使用DI。我认为以下是实现此问题的正确方法。

public UserService(IHttpContextAccessor httpContextAccessor, AutomationDbContext automationDbContext, IConfiguration configuration)
    {
        this.configuration = configuration;
        this.optionsBuilder = new DbContextOptionsBuilder<AutomationDbContext>();
        var connectionString = this.configuration.GetConnectionString("Automation");
        this.optionsBuilder.UseSqlServer(connectionString);
        this.automationDbContext = new AutomationDbContext(this.optionsBuilder.Options);
        this.httpContext = httpContextAccessor.HttpContext;
    }

我不喜欢在构造函数中构建optionsbuilder并获取连接字符串。 构建这些optionsBuilder并传递构造函数的更好的地方是什么。

1 个答案:

答案 0 :(得分:1)

您需要改用services.AddDbContext<TContext>

services.AddDbContext<AutomationDbContext>(o =>
    o.UseSqlServer(Configuration.GetConnectionString("Automation")));

然后,插入您的上下文:

public UserService(IHttpContextAccessor httpContextAccessor, AutomationDbContext automationDbContext)

对于IHttpContextAccessor,您只需使用:

services.AddHttpContextAccessor();

但是,我鼓励您强烈考虑您是否真的需要服务中的服务。如果您需要类似当前用户ID的信息,则应将其传递到需要它的方法中,而不是从服务中检索到。

更新

自从提出以来,让我解释一下为什么以您当前不正确的方式添加上下文是不正确的原因,因为这将使DI的总体工作原理有所了解。

首先,您将DbContext直接绑定到AutomationDbContext,这意味着您只能使用一个上下文。也许您现在不需要多个上下文。以后可能会改变。其次,当您以这种方式注册服务时,只能注入抽象类型,即此处的DbContext。服务注册的字面意思是“当您看到DbContext时,注入AutomationDbContext的实例”。如果您尝试像当前在控制器中那样直接注入AutomationDbContext,则实际上将引发异常,因为该类型实际上并未注册为服务:DbContext是。第三,AddScoped没有提供配置上下文的真正能力,这当然是您缺少的部分。有一些方法可以解决此问题,例如使用AddScoped的工厂重载或在上下文中定义OnConfiguring,但是这两种方法都不符合首先使用正确方法的标准:{{1} }

出于价值考虑,还有第四点原因,因为您可以选择使用AddDbContext<TContext>代替AddDbContextPool<TContext>进行连接池。没有其他方法可以进行设置,因此,如果您确实需要/需要连接池,那么您将永远无法使用AddDbContext<TContext>来实现。