Ninject - 当RequestScope无意义时,DbContext应该绑定在哪个范围?

15

在MVC/WebAPI环境中,我会使用InRequestScope来绑定DbContext

然而,我现在在一个控制台应用程序/Windows服务/Azure工作角色中(不太重要,只是没有Web请求范围),它会周期性地创建多个异步运行的Tasks。我希望每个任务都有自己的DbContext,并且由于任务在自己的线程上运行,所以我尝试使用InThreadScope来绑定DbContext

不幸的是,我发现当任务完成时,DbContext没有被释放。实际上,线程返回到线程池后,当它被分配一个新的任务时,它已经有了一个DbContext,因此DbContexts会一直保持活动状态。

InThreadScope是否可以在这里使用,或者我应该使用其他范围?当线程不断从线程池返回时,如何使用ThreadScope?


@Steven 是的,我明白了。那么如何实现自定义作用域(或其他解决方案)? - zafeiris.m
1
你根本不应该使用作用域。使用工厂来创建 DbContext(基本上是一个 工作单元)- 并根据需要传递它。如果软件保持像你描述的那样简单,你也可以使用命名范围(由任务定义,并绑定 DbContext InNamedScope)。但是,当你想在任务之外创建 DbContext 或者想在单个任务中有多个(连续的)DbContext 时,这种方法就不具备未来可扩展性了,等等。 - BatteryBackupUnit
我倾向于不同意@BatteryBackupUnit的观点,但最佳方法取决于您的应用程序。在我看来,“正确”的解决方案是针对每个操作显式地启动一个“作用域”,尽管我不知道如何在Ninject中实现这一点。如果想了解何时使用工厂以及何时注入UoW本身,请参阅此处。答案涉及Web应用程序,但适用于处理某些请求的任何应用程序。 - Steven
2
@Steven 我完全同意。为了澄清给其他读者:Ninject具有“范围”概念。在范围内绑定告诉ninject何时创建实例以及何时重用实例。我们没有使用那种范围。此外,我不会完全说我们将其与请求耦合。我们有WCF请求和来自硬件设备的事件。一些WCF请求或事件可能会指示我们执行几个需要多个工作单元的操作,有时甚至是异步的或稍后(如计划或其他)。有时需要工作单元的操作可能会嵌套。 - BatteryBackupUnit
1
@WahidBitar 是的:1)使用工厂创建UnitOfWork,在结束时传递它并处置它,2)使用工厂创建UnitOfWork,并使用类似于"TaskLocal"这样的东西访问它,而无需传递它。 - BatteryBackupUnit
显示剩余5条评论
1个回答

2
如果您决定使用自定义作用域,则解决方案如下:
public sealed class CurrentScope : INotifyWhenDisposed
{
    [ThreadStatic]
    private static CurrentScope currentScope;

    private CurrentScope()
    {
    }

    public static CurrentScope Instance => currentScope ?? (currentScope = new CurrentScope());

    public bool IsDisposed { get; private set; }

    public event EventHandler Disposed;

    public void Dispose()
    {
        this.IsDisposed = true;
        currentScope = null;
        if (this.Disposed != null)
        {
            this.Disposed(this, EventArgs.Empty);
        }
    }
}

Binding:

Bind<DbContext>().To<MyDbContext>().InScope(c => CurrentScope.Instance)

最后:
using (CurrentScope.Instance)
{
    // your request...
    // you'll get always the same DbContext inside of this using block
    // DbContext will be disposed after going out of scope of this using block
}

这个是否需要在 using 块内解决依赖关系才能正常工作? - IronSean
@IronSean,是的,using块定义了您的依赖项的生命周期。 - Jan Muncinsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接