繁体   English   中英

如何使用.Net Core 2.1配置依赖项注入的DbContext?

[英]How do I configure a DbContext with dependency injection with .Net Core 2.1?

服务

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上下文)
Microsoft.Extensions.Internal.PropertyHelper.CallNullSafePropertyGetter [TDeclaringType,TValue](Func`2 getter,Object target)的Microsoft.EntityFrameworkCore.DbContext.get_ChangeTracker()的Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()的Microsoft.AspNetCore.Mvc Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext,IModelBinder modelBinder,IValueProvider valueProvider,ParameterDescriptor参数,ModelMetadata元数据,对象值)的.ModelBinding.Binders.ComplexTypeModelBinder.BindModelCoreAsync(ModelBindingContext bindingContext)
在Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider。<> c__DisplayClass0_0。<g__Bind | 0> d.MoveNext()

当我从上下文中删除空的构造函数时发生异常

System.InvalidOperationException:无法创建类型为'Skillcheck.Models.TicketsystemContext'的实例。 模型绑定的复杂类型不能为抽象或值类型,并且必须具有无参数构造函数。 或者,给'c'参数一个非空的默认值。 在Microsoft.AspNetCore.Mvc.ModelBindingContext.Binders.ComplexTypeModelBinder.BindModelCoreAsync(ModelBindingContext bindingContext)在Microsoft.AspNetCore.Mvc.ModelBindingContext。 actionContext,IModelBinder modelBinder,IValueProvider valueProvider,ParameterDescriptor参数,ModelMetadata元数据,对象值)
在Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider。<> c__DisplayClass0_0。<g__Bind | 0> d.MoveNext()

  • 服务中的cs不为null,并成功从appsettings.json读取字符串
  • 在services.AddDbContext之后,上下文在ServiceCollection中,并且不会抛出
  • 在上下文构造函数中使用通用DbContextOptions代替DbContextOptions <TicketsystemContext>无效
  • 显式添加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时有效,但在注入时配置时无效。

好吧,第一个错误是由于包含无参数的构造函数。 那不应该存在。 依赖注入将始终选择要满足的依赖关系最少的构造函数,这将是无参数的,但是您需要注入DbContextOptions<TContext>

第二个错误表明您将上下文作为参数包含在操作方法中。 我不确定为什么要这么做,但不应该这么做。 您的上下文应注入控制器本身,并在此上设置为ivar,以便您的操作可以利用ivar。 可能可以在[FromServices]加上参数,以指示modelbinder应该忽略它,而应该从服务集合中注入它,但是方法注入是一种反模式。

您正在将TicketsystemContext直接注入Index动作。

通常,应将TicketsystemContext作为依赖项注入contructor中,如下所示:

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());
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM