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作用域中实现工厂,但失败了(请参阅我的更新)