【问题标题】:How do I configure a DbContext with dependency injection with .Net Core 2.1?如何使用 .Net Core 2.1 配置具有依赖注入的 DbContext?
【发布时间】:2019-05-07 01:04:51
【问题描述】:

服务

public void ConfigureServices(IServiceCollection services)
{
    string cs = Configuration.GetConnectionString("Skillcheck"); 
    services.AddDbContext<TicketsystemContext>(options => options.UseSqlServer(cs));
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

上下文

public TicketsystemContext()
{
}

public TicketsystemContext(DbContextOptions<TicketsystemContext> options)
    : base(options)
{
}

// ... rest of the context

例外

System.InvalidOperationException:没有数据库提供程序 为此 DbContext 配置。可以通过以下方式配置提供程序 覆盖 DbContext.OnConfiguring 方法或使用 AddDbContext 在应用服务提供商上。如果使用 AddDbContext,则 还要确保您的 DbContext 类型接受 DbContextOptions 对象在其构造函数中并将其传递给 DbContext 的基本构造函数。在 Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, IDbContextOptions contextOptions, DbContext context)
在 Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider() 在 Microsoft.EntityFrameworkCore.DbContext.get_ChangeTracker() 在 Microsoft.Extensions.Internal.PropertyHelper.CallNullSafePropertyGetter[TDeclaringType,TValue](Func`2 吸气剂,对象目标)在 Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.BindModelCoreAsync(ModelBindingContext 绑定上下文)在 Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext、IModelBinder modelBinder、IValueProvider valueProvider、 ParameterDescriptor 参数、ModelMetadata 元数据、对象值)
在 Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider.c__DisplayClass0_0.d.MoveNext()

当我从上下文中删除空构造函数时出现异常

System.InvalidOperationException:无法创建类型的实例 'Skillcheck.Models.TicketsystemContext'。模型绑定的复杂类型 不能是抽象类型或值类型,并且必须具有无参数 构造函数。或者,给“c”参数一个非空默认值 价值。在 Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.CreateModel(ModelBindingContext 绑定上下文)在 Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.BindModelCoreAsync(ModelBindingContext 绑定上下文)在 Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext、IModelBinder modelBinder、IValueProvider valueProvider、 ParameterDescriptor 参数、ModelMetadata 元数据、对象值)
在 Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider.c__DisplayClass0_0.d.MoveNext()

  • Service 中的 cs 不为空,并从 appsettings.json 成功
  • 在 services.AddDbContext 之后,上下文位于 ServiceCollection 中 它不会抛出
  • 使用通用 DbContextOptions 而不是 上下文构造函数中的 DbContextOptions 不工作
  • 显式添加 IHttpContextAccessor 也不起作用

我通过覆盖 OnConfiguring 暂时解决了它,但我想了解它为什么不起作用。 我在 VS2017 上使用 .Net Core 2.1。

解决方案

错误是,而不是

private TicketsystemContext _c;

public HomeController(TicketsystemContext c)
{
    _c = c;
}

public IActionResult Index()
{
    return View(_c.User.First());
}

我用过

public IActionResult Index(TicketsystemContext c)
{
    return View(c.User.First());
}

在覆盖 OnConfiguring 时有效,但在注入时配置时无效。

【问题讨论】:

  • 您的代码看起来不错。您是否也明确注册了 IHttpContextAccessor ? services.TryAddSingleton&lt;IHttpContextAccessor, HttpContextAccessor&gt;();
  • @Mausam:这完全没有必要,与这里的问题无关。
  • 哪一行抛出第二个错误?一个可重现的演示会很有帮助。
  • @Mausam 我已经尝试过了,但忘记提及了。我现在已经添加了。
  • @TaoZhou CreateWebHostBuilder(args).Build().Run()中的运行;抛出它。 Startup.Configure 方法没有显示任何问题,因此它会在此之后抛出。我认为 Chris 正在做某事,所以我会等到我尝试重现。

标签: c# asp.net-core dependency-injection asp.net-core-mvc asp.net-core-2.1


【解决方案1】:

您将TicketsystemContext 直接注入Index 操作。

一般情况下,您应该将TicketsystemContext 作为依赖注入到构造函数中,如下所示:

public class HomeController : Controller
{
    private readonly TicketsystemContext context;
    public HomeController(TicketsystemContext context)
    {
        this.context = context;
    }
    public IActionResult Index()
    {
        return View(context.User.First());
    }
}

如果您更喜欢将TicketsystemContext 注入行动,您可以通过以下代码尝试@Chris Pratt 的建议:

public IActionResult Index([FromServices]TicketsystemContext c)
{
    return View(c.User.First());
}

【讨论】:

    【解决方案2】:

    嗯,第一个错误是由于包含了无参数构造函数。那不应该存在。依赖注入将始终选择满足最少依赖的构造函数,这将是无参数的,但您需要DbContextOptions&lt;TContext&gt;注入。

    第二个错误表明您将上下文作为参数包含在操作方法中。我不确定你为什么要这样做,但你不应该这样做。您的上下文应该被注入到控制器本身并在其上设置为 ivar,因此您的操作可以利用 ivar。您也许可以在参数前面加上[FromServices] 以指示模型绑定器应该忽略它并且应该从服务集合中注入它,但是方法注入是一种反模式。 p>

    【讨论】:

    • 我不确定我在哪里使用动作方法。为了清楚起见,我添加了完整的 ConfigureService。
    • 它将在您的一个控制器中,而不是您的 Startup 中。换句话说,在你删除无参数构造函数之后,你就很好了。第二个错误是一个完全不同的问题。
    • 无参数构造函数无关紧要,但我会记住你所说的。最后就是你说的,直接注入控制器。在道的代码之前,我只是不懂行话。
    猜你喜欢
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-19
    • 1970-01-01
    • 2020-09-12
    • 2016-05-22
    • 1970-01-01
    相关资源
    最近更新 更多