【问题标题】:Entity Framework + Life Time + StructureMap + Unit Of Work + Windows Forms?实体框架 + 生命周期 + StructureMap + 工作单元 + Windows 窗体?
【发布时间】:2011-05-02 17:35:57
【问题描述】:

我有一个 windows 服务(或 Windows 窗体),当计时器到时,我的服务会完成一些任务。

只要我的应用正在运行,我就不想只使用一个实体框架上下文

我看到了 NHibernate 中的会话工厂 示例。 EF 有类似的东西吗?

以下是我在 ASP.NET 或 MVC 应用程序中使用 EF + StructureMap 的方法:

应用开始:

ObjectFactory.Configure(Function(config) config.For(Of IUnitOfWork).HybridHttpOrThreadLocalScoped.Use(Of UnitOfWork)())

结束请求:

ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects()

我的UnitOfWork根据网络请求启动的,并在请求结束后处置

在我的 Win App 场景中,UoW 应该在计时器经过并在我的工作完成后处置并且 我不想处理它时启动我自己。

如何在 Windows 窗体应用程序中实现类似的功能?

如果我使用 HybridHttprThreadLocalScoped 注册我的 UoW,每个线程只有一个 UoW,如果我丢弃它,它就消失了

编辑:

我在 dll 中有我的存储库 + 服务,我想在 web 或 win 应用程序中使用它们,正因为如此我用HybridHttpOrThreadLocalScoped

更新 2:

这是我的存储库

Public Class ProductRepository

    Private ReadOnly _databaseFactory As DataAccess.IDatabaseFactory

    Public Sub New(ByVal databaseFactory As DataAccess.IDatabaseFactory)
        _databaseFactory = databaseFactory
    End Sub

    Public Function GetById(ByVal id As Integer) As Product
        Return (From item In _databaseFactory.GetDataContext.Products Where item.ProductId = id).FirstOrDefault
    End Function

End Class

这是我的服务

Public Class ProductService

    Private ReadOnly _Repository As ProductRepository

    Public Sub New(ByVal repository As ProductRepository)
        _Repository = repository
    End Sub

    Public Function GetById(ByVal id As Integer) As Product
        Return _Repository.GetById(id)
    End Function

End Class

我正在使用 StructureMap。 StructureMap 在 web 场景中接管了我的 DatabaseFactoryUoW 生命周期。但我不知道在 win apps 中该做什么。我可以管理 UoW 我自己的生命周期,但我正在寻找一种方法,以便 StructureMap 为我处理它,因为它可以处理网络应用程序中的生命周期。

【问题讨论】:

  • Afshin 我也有类似的问题。你能分享你的最终解决方案吗?
  • @shaahin:我目前的解决方案并不完美。我会尽快将其添加到此帖子中。在网络应用程序中,请求的开始和结束由框架发出信号,但在 Windows 应用程序中,情况并非如此,所以我手动进行并模拟它。例如:在某个按钮的单击处理程序方法(在 win 应用程序中)我正在向我自己的基础架构发出请求的开始和结束信号。

标签: c# .net entity-framework structuremap unit-of-work


【解决方案1】:

ASP.Net 提供了管理对象上下文生命周期的基础结构(基本上每个请求一个 httpcontext)。 winforms(显然)没有类似的东西。因此,管理 EF 上下文的方式很大程度上取决于您的应用程序架构。

例如,如果您有一个 MVP 或 MVVM 风格的应用程序,您可以将上下文的生命周期与 Presenter 或 ViewModel 的生命周期结合起来。或者,您可以采用“用户故事”的抽象概念,并将对象上下文的生命周期与此相结合。这真的取决于。

为了获得灵感,look at this article by Ayende(这是关于 NHibernate 的会话管理,但概念是相同的。想想 NHibernate Session == Entity Framework ObjectContext)

【讨论】:

  • 感谢您的回复。我读过你提到的那篇文章。问题是:在 web 应用程序中,结构图启动并为每个会话处理我的 UoW。在 win 应用程序中,结构图为每个线程启动一个 UoW,如果我管理它的生命周期并在我的演示者被处理后处理它,Uow 消失了,但线程仍然存在!我认为我应该更多地研究结构图,正如你所说,它在很大程度上取决于我的应用程序的架构。
  • @Afshin Gh 我不认为 uow 生命周期应该由 IoC 容器管理,它应该是明确的(至少在桌面应用程序中
  • 是的。我找不到更好的方法。看起来我必须在 win 应用程序中自己管理它。我会再等一下其他答案。 (并投票赞成你的答案。)
【解决方案2】:

Web 应用程序是无状态,而桌面应用程序是有状态。在 web 中,对象通常是按请求创建的,并且同样被处理掉。这样做的原因有很多(比如处理多个请求和有限的内存量等),这就是为什么你已经准备好所有的基础设施。在桌面中,您可以将所有内容存储在内存中。

因此,在桌面应用程序中,您需要手动实现会话管理(通常是每个业务事务)。

更新:this post 在会话中有相关代码

【讨论】:

  • 我完全了解 web 和 win 应用程序之间的差异。在 NHibernate 中,您有会话工厂。在 EF 中等于什么?
  • @Afshin Gh 抱歉回答毫无意义。也许你可以看到这个帖子? peplowdown.wordpress.com/2010/07/05/… 这家伙用 EF 创建会话工厂和会话。
  • 您链接的文章不是我想要的,但它很有用。感谢您的帮助,我投票赞成您的回答,我会等待其他人投票和回答。
【解决方案3】:

实体框架为您提供“上下文”,它是一种在其内部具有工作单元范围的会话,为一个上下文完成的所有操作都保留在上下文范围内。实体框架已经实现了工作单元模式。 EF 还实现了标识映射,因此对于一个主键,您会发现在导航属性中到处都引用了一个对象。

对于桌面应用程序,您只需要维护一个上下文,它将是所有操作的范围,并且它将所有操作存储在正确的状态,直到您调用 SaveChanges。

对于 Web 应用程序,您可以将上下文放在 ASP.NET 的 Session 中,这可能会增加服务器的负载,但它可能允许您将更改存储更长的时间,而不是单个页面。

只要我的应用程序正在运行,我就不想只使用一个实体框架上下文。

只要应用程序正在运行,一个上下文有什么问题?相反,这是正确的方法。保持一个上下文处于活动状态并不意味着您保持与数据库的连接处于活动状态。数据库连接仅在查询和保存更改时打开和关闭。

如果您的应用几乎没有失去平衡并导致内存问题,最好的方法是分配新上下文并刷新您的 UI,它会将所有旧上下文及其对象放入垃圾收集器中,而您的新上下文将为您提供内存较小。

【讨论】:

  • 只要我的 win 应用程序正在运行,我就不喜欢让我的上下文保持活跃。当我需要它时启动我的 UoW 并在工作完成后关闭它,对我来说看起来更好。但你是完全正确的,你的答案很有用。投票赞成。
  • ObjectContext 并不是一个长期存在的对象。让它保持活动状态并不是最佳做法(a.o. 因为您查询的所有内容都保留在缓存中,所以它保持活动状态的时间越长,您在多用户环境中查看陈旧数据的机会就越大)
  • @jeroenh,如果您阅读了我的回答,我不建议任何人在多用户环境中将 ObjectContext 保留更长时间,对于单用户来说,最好和最首选的方法是让它长期存在因为无论如何您都会将对象保存在内存中,以便显示以供查看和编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-11
  • 2015-06-30
相关资源
最近更新 更多