使用Unity与在WinForms应用程序中保存DBContext的类

时间:2016-01-11 08:45:08

标签: c# winforms dependency-injection inversion-of-control unity-container

我有一个使用Unity for DI的N层WinForms应用程序。 Main的启动如下:

static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    var container = new UnityContainer();
    container.RegisterType<IProductRequestRepository, MDIS.DAL.Repositories.Specific.ProductRequestRepository>();
    container.RegisterType<IProductRequestServices, ProductRequestServices>();

    var form = container.Resolve<MdisMain>();

    Application.Run(form);
}

IDisposable在存储库(ProductRequestRepository)中实现。 ProductRequestServices类的实例由主WinForm持有。除非应用程序关闭,否则不会发布。 ProductRequestServices类还有一个ProductRequestRepository实例。每次主窗口启动浏览表单时都会使用存储库,该表单使用存储库来使用实体框架获取条目列表。存储库具有在实例化时创建的DBContext实例。我在存储库实现Dispose方法中放置了断点,但它们永远不会被调用,可能是因为ProductRequestServices对象持有存储库的实例。

如果我在浏览窗口关闭时添加代码以手动调用存储库实例上的Dispose,则在重新打开浏览窗口时会出现错误,说明该对象为空,因此我猜Unity不会重新实例化该对象再次,仅在组合根中的应用程序的开始。

在这种情况下,每次创建浏览窗口时我是否应该重新实例化我的存储库类以确保DBContext是新的而不是以前的内容?这是我打算做的事情,除非我能做Unity的其他事情。一旦主窗体打开,我就无法再次调用Resolve或任何Unity方法,因为我的Unity容器的范围仅限于我之前显示的启动主程序文件。我该怎么做才能解决这个问题?提前谢谢。

****更新于2016年1月11日下午9:40

目前,解决这个问题的最简单方法是删除Unity容器,然后在using语句中包装由主WinForm的菜单选项启动的表单调用,如下所示:

private void detailReportListToolStripMenuItem_Click_1(object sender, EventArgs e)
{
    using (UnitOfWork aUnitOfWork = new UnitOfWork())
    {
        ProductRequestServices aProductRequestServices = new ProductRequestServices(aUnitOfWork);
        ProductRequestList aProductRequestList = new ProductRequestList(aProductRequestServices);
        aProductRequestList.ShowDialog();
        aProductRequestList.Close();
    }
}

我还从我的存储库中删除了DBContext内部实例,并将其放入UnitOfWork类中。上面的示例允许我的UnitOfWork类使用其内部DBContext进行实例化,并传递给表单,以便在存储库调用时使用它。当窗体关闭时,UnitOfWork被释放,导致它的Dispose实现运行并释放它由表单使用的DBContext。每次打开表单时,我都会得到一个新的DBContext实例。当我在应用程序的开头使用Unity容器时,它保存在ProductRequestServices类实例的单个实例上,这导致了不释放DBContext的问题。手动尝试释放DBContext只会导致更多问题,所以这种方法现在会做。

1 个答案:

答案 0 :(得分:0)

解决这个问题的建议是:

  • 确保每次调用某个服务来完成某项工作时,它会在它完成工作后立即处理(这也需要它不具有状态)。
  • 将依赖注入从构造函数参数切换到基于属性。

这应该确保每次调用与数据库一起工作的服务时,它都会获得dbcontext的全新实例。