如何使用 .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: No database provider has been
configured for this DbContext. A provider can be configured by
overriding the DbContext.OnConfiguring method or by using AddDbContext
on the application service provider. If AddDbContext is used, then
also ensure that your DbContext type accepts a
DbContextOptions object in its constructor and passes it to
the base constructor for DbContext. at
Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider
scopedProvider, IDbContextOptions contextOptions, DbContext context)
at
Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
at Microsoft.EntityFrameworkCore.DbContext.get_ChangeTracker() at
Microsoft.Extensions.Internal.PropertyHelper.CallNullSafePropertyGetter[TDeclaringType,TValue](Func`2
getter, Object target) at
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.BindModelCoreAsync(ModelBindingContext
bindingContext) at
Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext
actionContext, IModelBinder modelBinder, IValueProvider valueProvider,
ParameterDescriptor parameter, ModelMetadata metadata, Object value)
at
Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<g__Bind|0>d.MoveNext()
当我从上下文中删除空构造函数时出现异常
System.InvalidOperationException: Could not create an instance of type
'Skillcheck.Models.TicketsystemContext'. Model bound complex types
must not be abstract or value types and must have a parameterless
constructor. Alternatively, give the 'c' parameter a non-null default
value. at
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.CreateModel(ModelBindingContext
bindingContext) at
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.BindModelCoreAsync(ModelBindingContext
bindingContext) at
Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext
actionContext, IModelBinder modelBinder, IValueProvider valueProvider,
ParameterDescriptor parameter, ModelMetadata metadata, Object value)
at
Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<g__Bind|0>d.MoveNext()
- 服务中的 cs 不为空并从中读取字符串
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 时有效,但在注入时配置时无效。
好吧,第一个错误是由于包含了无参数构造函数。那不应该存在。依赖注入总是会选择满足最少依赖的构造函数,这将是无参数的,但是你 need DbContextOptions<TContext>
injected.
第二个错误表明您将上下文作为参数包含在操作方法中。我不确定你为什么这样做,但你不应该这样做。你的上下文应该被注入到控制器本身并设置为一个ivar,这样你的动作就可以利用这个ivar。您 可能 可以在参数前面加上 [FromServices]
以指示模型绑定器应该忽略它并且应该从服务集合中注入它,而不是,但是方法注入是一种反-模式。
您正在将 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());
}
服务
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: No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext. at Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, IDbContextOptions contextOptions, DbContext context)
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider() at Microsoft.EntityFrameworkCore.DbContext.get_ChangeTracker() at Microsoft.Extensions.Internal.PropertyHelper.CallNullSafePropertyGetter[TDeclaringType,TValue](Func`2 getter, Object target) at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.BindModelCoreAsync(ModelBindingContext bindingContext) at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)
at Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<g__Bind|0>d.MoveNext()
当我从上下文中删除空构造函数时出现异常
System.InvalidOperationException: Could not create an instance of type 'Skillcheck.Models.TicketsystemContext'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Alternatively, give the 'c' parameter a non-null default value. at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.CreateModel(ModelBindingContext bindingContext) at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.BindModelCoreAsync(ModelBindingContext bindingContext) at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)
at Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<g__Bind|0>d.MoveNext()
- 服务中的 cs 不为空并从中读取字符串 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 时有效,但在注入时配置时无效。
好吧,第一个错误是由于包含了无参数构造函数。那不应该存在。依赖注入总是会选择满足最少依赖的构造函数,这将是无参数的,但是你 need DbContextOptions<TContext>
injected.
第二个错误表明您将上下文作为参数包含在操作方法中。我不确定你为什么这样做,但你不应该这样做。你的上下文应该被注入到控制器本身并设置为一个ivar,这样你的动作就可以利用这个ivar。您 可能 可以在参数前面加上 [FromServices]
以指示模型绑定器应该忽略它并且应该从服务集合中注入它,而不是,但是方法注入是一种反-模式。
您正在将 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());
}