我正在尝试创建一个UnitOfWork Action Filter。
我已经挂钩OnActionExecuted方法,我希望根据三条规则保存对DBContext的所有更改: -
在整个WEB API中的操作方法中,我只将实体附加到DbContext,它只在动作本身完成而没有任何错误时才提交更改。
使用Ninject进行设置的DbContext,其生活方式为" InRequestScope"。
这是UnitOfWork ActionFilterAttribute: -
public class UnitOfWorkActionFilterAttribute : ActionFilterAttribute
{
public virtual IActionTransactionHelper ActionTransactionHelper
{
get { return WebContainerManager.Get<IActionTransactionHelper>(); }
}
public override bool AllowMultiple
{
get { return false; }
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
ActionTransactionHelper.BeginTransaction();
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
ActionTransactionHelper.EndTransaction(actionExecutedContext);
ActionTransactionHelper.CloseSession();
}
}
在Ninject中,DbContext的配置如下: -
container.Bind<MyDbContext>().ToSelf().InRequestScope();
这是ActionTransactionHelper类: -
public class ActionTransactionHelper : IActionTransactionHelper
{
public bool TransactionHandled { get; private set; }
public bool SessionClosed { get; private set; }
public void BeginTransaction()
{
var sessionContext = WebContainerManager.Get<MyDbContext>();
if (sessionContext == null)
{
throw new NullReferenceException("sessioncontext");
}
}
public async Task EndTransaction(HttpActionExecutedContext filterContext)
{
var sessionContext = WebContainerManager.Get<MyDbContext>();
if (sessionContext != null && sessionContext.ChangeTracker.HasChanges() && filterContext.Exception == null)
{
var x = await sessionContext.SaveChangesAsync();
}
TransactionHandled = true;
}
public void CloseSession()
{
var sessionContext = WebContainerManager.Get<MyDbContext>();
if (sessionContext == null) return;
sessionContext.Dispose();
SessionClosed = true;
}
}
我有一个Action方法,它将enities连接到DBContext,如下所示: -
context.Claims.Add(entity);
当在ActionExecuted上触发EndTransaction()方法时,上下文对象在ChangeTracker中没有任何更改的记录,并且永远不会触发SaveChangesAsync()方法。
但是,如果我将DbContext的Ninject Binding更改为Singleton,代码工作正常,跟踪更改并将对象保存到数据库。
我不明白为什么这不是每个网络请求都有效?
在这种情况下,我不想使用Singletons。
答案 0 :(得分:1)
通过添加Ninject.WeApi2 Nuget Package解决了这个问题。
在NinjectWebCommon中,我将NinjectDependencyResolver实现替换为Ninject.WeApi2中引用的实现
**Ninject.Web.WebApi.NinjectDependencyResolver**
InRequestScope()现在可以正常使用Action Filters,DBContext可以跟踪更改。