我有一个MVC3项目,它使用Ninject,Entity Framework和工作单元模式与服务层。
我的AsyncService类有一个启动后台任务的函数,作为示例,它将用户添加到用户存储库。 我当前的问题是,在我收到DbContext已被处理的错误之前,该任务只能正确运行几秒钟。 使用Ninject的InRequestScope()注入的我的数据库上下文似乎正在处理,因为InRequestScope()将它绑定到HttpContext。
我已经读过InThreadScope(),但是我不确定如何在我的MVC项目中正确实现它。
我的问题是:在我的任务中使用Ninject的正确方法是什么?
public class AsyncService
{
private CancellationTokenSource cancellationTokenSource;
private IUnitOfWork _uow;
public AsyncService(IUnitOfWork uow)
{
_uow = uow;
}
public void AsyncStartActivity(Activity activity)
{
...snip...
this.cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = this.cancellationTokenSource.Token;
var task = Task.Factory.StartNew(() =>
{
foreach (var user in activity.UserList)
{
this._uow.UserRepository.Add(new User() {UserID = user});
}
this._uow.Save();
}, cancellationToken);
...snip...
}
}
答案 0 :(得分:5)
InRequestScope
'对象在请求结束时为Dispose
d,因此在这种情况下不能使用它。 InThreadScope
也不适合将UoW用于多个任务。
您可以做的是将AsyncService
声明为使用NamedScope扩展名的所有对象的作用域对象。
请参阅http://www.planetgeek.ch/2010/12/08/how-to-use-the-additional-ninject-scopes-of-namedscope/
答案 1 :(得分:0)
这是一个混乱的解决方案,我过去使用过ChildKernel插件(我认为命名范围会更清晰)。基本上我创建了一个子内核,并将与UoW相关的所有内容作为子内核中的单例。然后,我为每个Task创建一个新的子内核,处理UoW,然后提交或回滚。
IAsyncTask
是一个包含1个方法的接口Execute()
private Task void ExecuteTask<T>() where T:IAsyncTask
{
var task = Task.Factory.StartNew(() =>
{
var taskKernel = _kernel.Get<ChildKernel>();
var uow = taskKernel.Get<IUnitOfWork>();
var asyncTask = taskKernel.Get<T>();
try
{
uow.Begin();
asyncTask.Execute();
uow.Commit();
}
catch (Exception ex)
{
uow.Rollback();
//log it, whatever else you want to do
}
finally
{
uow.Dispose();
taskKernel.Dispose();
}
});
return task;
}