Asp.net mvc 4 在RequestScope中注入DbContext不会返回相同的对象实例
问题:Asp.net mvc 4 在RequestScope中注入DbContext不会返回相同的对象实例,asp.net-mvc-4,dependency-injection,entity-framework-5,ninject,Asp.net Mvc 4,Dependency Injection,Entity Framework 5,Ninject,问题: [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)] public class UnitOfWorkAttribute : Attribute { } public class UnitOfWorkFilter : IActionFilter { private readonly IUnitOfWork unitOfWo
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class UnitOfWorkAttribute : Attribute { }
public class UnitOfWorkFilter : IActionFilter
{
private readonly IUnitOfWork unitOfWork;
public UnitOfWorkFilter(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
public void OnActionExecuting(ActionExecutingContext filterContext) { }
public void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Exception == null)
{
unitOfWork.Commit();
}
}
}
kernel.Bind<IUnitOfWork>().To<BudgetContext>().InRequestScope();
kernel.BindFilter<UnitOfWorkFilter>(FilterScope.Action, 0).WhenActionMethodHas<UnitOfWorkAttribute>();
我在Web应用程序中使用Ninject作为IoC框架。我尝试将Entity Framework DbContext类注入代码中的几个类。我想按请求共享一个对象实例。因此,我尝试使用ninject中的InRequestScope方法。问题是实例没有共享。相反,我总是得到一个DbContext的新实例
代码:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class UnitOfWorkAttribute : Attribute { }
public class UnitOfWorkFilter : IActionFilter
{
private readonly IUnitOfWork unitOfWork;
public UnitOfWorkFilter(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
public void OnActionExecuting(ActionExecutingContext filterContext) { }
public void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Exception == null)
{
unitOfWork.Commit();
}
}
}
kernel.Bind<IUnitOfWork>().To<BudgetContext>().InRequestScope();
kernel.BindFilter<UnitOfWorkFilter>(FilterScope.Action, 0).WhenActionMethodHas<UnitOfWorkAttribute>();
首先,我实现了DbContext类:
public class BudgetContext : DbContext, IUnitOfWork
{
public BudgetContext() : base("DefaultConnection")
{
Database.SetInitializer<BudgetContext>(new DropCreateDatabaseIfModelChanges<BudgetContext>());
}
public DbSet<Expense> Expenses { get; set; }
public int Commit()
{
return SaveChanges();
}
}
对于一个请求,两个注入的DbContext类应该是相同的对象实例。NinjectWebCommon.cs中的Ninject配置如下所示:
...
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>().To<BudgetContext>().InRequestScope();
kernel.Bind<IExpenseRepository>().To<ExpenseRepository>();
// ...
kernel.Bind<ExpensesController>().To<ExpensesController>();
}
...
public class UnitOfWorkFactory : IUnitOfWorkFactory
{
private IUnitOfWork unitOfWork;
public IUnitOfWork Get()
{
if (unitOfWork == null)
unitOfWork = new BudgetContext();
return unitOfWork;
}
}
在Ninject中,我为新工厂使用以下配置:
kernel.Bind<IUnitOfWorkFactory>().To<UnitOfWorkFactory>().InRequestScope();
不幸的是,我没有成功。My DbContext总是在到达属性类后重置。您需要三个包
Ninject
Ninject.Web
Ninject.Web.Common
然后您应该在两个库中注册Ninject.Web.Common
和Ninject.Web
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof (OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof (Ninject.Web.Common.NinjectHttpModule));
DynamicModuleUtility.RegisterModule(typeof (Ninject.Web.NinjectHttpModule));
bootstrapper.Initialize(createKernel);
}
我不确定是否需要添加
Bind()。ToSelf()
过滤器由MVC框架缓存。不要使用InRequest作用域引用,而是注入工厂
多亏了@Remo Gloor,我发现我的属性肯定有问题。因此,我更改了实现并实现了接口IActionFilter,而不是继承类ActionFilterAttribute。现在我可以在request作用域中插入DbContext 属性:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class UnitOfWorkAttribute : Attribute { }
public class UnitOfWorkFilter : IActionFilter
{
private readonly IUnitOfWork unitOfWork;
public UnitOfWorkFilter(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
public void OnActionExecuting(ActionExecutingContext filterContext) { }
public void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Exception == null)
{
unitOfWork.Commit();
}
}
}
kernel.Bind<IUnitOfWork>().To<BudgetContext>().InRequestScope();
kernel.BindFilter<UnitOfWorkFilter>(FilterScope.Action, 0).WhenActionMethodHas<UnitOfWorkAttribute>();
绑定:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class UnitOfWorkAttribute : Attribute { }
public class UnitOfWorkFilter : IActionFilter
{
private readonly IUnitOfWork unitOfWork;
public UnitOfWorkFilter(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
public void OnActionExecuting(ActionExecutingContext filterContext) { }
public void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Exception == null)
{
unitOfWork.Commit();
}
}
}
kernel.Bind<IUnitOfWork>().To<BudgetContext>().InRequestScope();
kernel.BindFilter<UnitOfWorkFilter>(FilterScope.Action, 0).WhenActionMethodHas<UnitOfWorkAttribute>();
kernel.Bind().To().InRequestScope();
BindFilter(FilterScope.Action,0).WhenActionMethodHas();
我试过你的建议。很遗憾,没有成功。您能否简单描述一下在request作用域中实例化变量的代码在注入的factory中的外观?我尝试在request作用域中实现工厂,但失败了(请参阅我的更新)