将Unity与WinForms应用程序中包含DBContext的类一起使用时释放DBContext

本文关键字:DBContext 一起 释放 WinForms 应用程序 包含 Unity | 更新日期: 2023-09-27 18:29:43

我有一个使用Unity进行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,当重新打开浏览窗口时,我会收到一个错误,指出对象为null,所以我猜Unity不会再次重新实例化对象,只是在组合根中的应用程序开始时。

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

****更新时间:2016年11月1日上午9:40

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

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只会导致更多的问题,所以这种方法目前可以。

将Unity与WinForms应用程序中包含DBContext的类一起使用时释放DBContext

解决此问题的建议是:

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

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