【发布时间】:2012-03-30 00:29:23
【问题描述】:
我不确定如何结合 ORM 最好地实现主详细信息视图。 该应用程序将 WPF 与 MVVM 结合使用,并显示所有可用对象的网格以及当前选定对象的详细信息。
视图的 ViewModel 非常简单,它有:
-
ObservableCollection<ItemViewModel> Items其中ItemViewModel是应在视图中显示的域对象的视图模型。此属性绑定到网格。 - 绑定到网格的
SelectedItem的ItemViewModel CurrentItem属性。 -
ICommand用于“添加新项目”、“删除选定项目”和“保存对选定项目的更改”。
我的应用程序使用 NHibernate 作为其 ORM 工具,但我不想在整个代码库中泄漏 NHibernate,因此我使用“工作单元”和“存储库”模式将其抽象出来。
这些模式的 NHibernate 特定实现是这样的,“工作单元”在开始时打开一个新的 NHibernate 会话和事务,最后提交事务并处理会话。因此,工作单元、会话和事务的生命周期是相同的。工作单元有一个属性Repository,它使用与工作单元相同的会话,并且具有相同的生命周期。
这就是问题所在:
我想在MasterDetailViewModel 的构造函数中填充Items 集合。目前,我需要创建一个新的工作单元并填充集合。为了没有长时间运行的事务,UoW 将在之后直接处置,同时处置基础会话。
现在,当用户想要保存对当前项目的更改时,我需要打开另一个 UoW,从数据库中检索实体,使用 ItemViewModel 的当前值更新它,将其保存到数据库中并处置 UoW。
但是,这种方法有几个重要的缺点:
- 我的代码中到处都是
using(var uow = uowFactory.StartNew())。 - 没有发生乐观锁定。如果其他人更改了数据库中的相同项目,他的更改将被默默地覆盖。
- 更新项目需要两次数据库命中而不是一次。
这使我得出结论,即我的 UoW 的实施存在缺陷。
我考虑过更改实现,以便颠倒 UoW 和存储库之间的关系。这意味着 IoC 会将 Repository 注入 ViewModel 而不是 UnitOfWorkFactory。存储库现在是 NHibernate 的ISession 的功能等效项。存储库可以启动一个新的 UoW,它现在与数据库事务相同。
这很适合我的主/细节场景,但它不支持通常用作工作单元同义词的“业务事务”的概念,例如跨越多个数据库事务和用户请求的逻辑事务。
问题是:如何最好地实现工作单元和存储库这两种模式以在两种情况下都可用?
【问题讨论】:
-
我没有使用抽象,但我打开了一个长时间运行的会话,它填充网格并驱逐所有不再显示的项目(显示项目周围的框架除外)并使用 transaction.Begin() , transaction.Commit() 围绕每个业务操作“添加新”、“更改”等。
-
@Firo:感谢您再次向我保证,在这种情况下,长时间运行的会话是一件好事。
标签: c# .net nhibernate design-patterns architecture