我正在尝试使用Framework 4.6.1在我们的ASP.Net MVC 5 Web应用程序中使用EF Core。我们正在使用Ninject进行依赖注入。我在DAL层注入了Context。我成功执行单个查询,但上下文在运行下一个查询时抛出以下异常
没有为此DbContext配置数据库提供程序。可以通过覆盖DbContext.OnConfiguring方法或在应用程序服务提供程序上使用AddDbContext来配置提供程序。如果使用AddDbContext,那么还要确保您的DbContext类型在其构造函数中接受DbContextOptions对象,并将其传递给DbContext的基础构造函数。
我以前见过这个错误,但我不确定它在我的情况下是如何适用的。什么是我的设置导致此错误被抛出?这是一些代码:
控制者:
public ActionResult GetEnrollmentWorkflows()
{
var class1Entities = this._class1Service.GetAll().ToList();
var class1EntityIds = class1Entities.Select(x => x.Class1EntityId).ToList(); // Works
var class2Entity =
this._class2EntityService
.GetByClass1EntityIds(class1EntityIds).ToList(); // Fails with exception
return PartialView("_somePartial", model);
}
上下文绑定:
kernel.Bind<Context.ContextTenant>().ToSelf().InTransientScope()
.WithConstructorArgument("options",
new DbContextOptionsBuilder<Tables.ContextTenant>()
.UseSqlServer(ConfigurationManager.ConnectionStrings
[EnvironmentConsts.DbConnectionTenant].ConnectionString)
.Options);
上下文:
public ContextTenant(DbContextOptions<Tables.ContextTenant> options) : base(options)
{}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
}
Ninject模块:
public class DalModule : NinjectModule
{
public override void Load()
{
this.Kernel.Bind(x =>
x.FromThisAssembly().SelectAllClasses().Join
.FromAssemblyContaining<ISomeInterface>()
.SelectAllInterfaces()
.BindAllInterfaces().Configure(y => y.InTransientScope()));
}
}
public class ServiceModule : NinjectModule
{
public override void Load()
{
this.Kernel?.Load(new[] { new DalModule() });
this.Kernel.Bind(x =>
x.FromThisAssembly().SelectAllClasses().Join
.FromAssemblyContaining<ISomeInterface>()
.SelectAllInterfaces()
.BindAllInterfaces().Configure(y => y.InTransientScope()));
}
}
DAL课程
1类:
public class Class1Repository : IClass1Repository
{
private ContextTenant ContextTenant { get; }
public Class1Repository(ContextTenant contextTenant)
{
ContextTenant = contextTenant;
}
public IEnumerable<Class1Entity> GetAll()
{
return this.ContextTenant.Class1Entity.Select(x => x);
}
}
第2类:
public class Class2Repository : IClass2Repository
{
private readonly ContextTenant _contextTenant;
public Class2Repository(ContextTenant contextTenant)
{
_contextTenant = contextTenant;
}
public IEnumerable<Class2Entity> GetByClass1EntityIds(
IEnumerable<int> class1EntityIds)
{
return this._contextTenant.Class2Entity.Where(x =>
class1EntityIds.Contains(x.Class1EntityId));
}
}
服务:
public class Class1Service : IClass1Service
{
private readonly IClass1Repository _class1Repository;
public Class1Service(IClass1Repository class1Repository)
{
_class1Repository = class1Repository;
}
public IEnumerable<Class1Entity> GetAll()
{
return this._class1Repository.GetAll();
}
}
public class Class2Service : IClass2Service
{
private readonly IClass2Repository _class2Repository;
public Class2Service(IClass2Repository class2Repository)
{
_class2Repository = class2Repository;
}
public IEnumerable<Class2Entity> GetByClass1EntityIds(
IEnumerable<int> class1EntityIds)
{
return this._class2Repository.GetByClass1EntityIds(class1EntityIds);
}
}
编辑:以下是一些来自启动的代码,以防这会影响任何事情:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(NinjectWebCommon), "Stop")]
namespace MyApp
{
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
// Bind the context
}
}
}
根据我上面的内容,我相信这是因为您正在使用RequestScope。问题是db context将在每次使用后进行处理,因为你仍然在同一个请求中,当你再次调用它时它已经被处理掉了,但它却服务于同一个实例。将其更改为Transient(或与Ninject等效的Transient,意味着在每个请求上获取新的db上下文),它应该解决问题。
我过去遇到过类似的问题,有时可以通过改变来解决
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
}
在
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (optionsBuilder.IsConfigured == false)
{
base.OnConfiguring(optionsBuilder);
}
}