我不确定如何最好地结合 ORM 实现主细节 View 。 该应用程序将 WPF 与 MVVM 结合使用,并显示所有可用对象的网格以及当前所选对象的详细信息。
View 的 ViewModel 非常简单,它有:
- 安
ObservableCollection<ItemViewModel> Items
其中ItemViewModel
是应该在 View 中显示的域对象的 ViewModel。此属性绑定(bind)到网格。 - A
ItemViewModel CurrentItem
绑定(bind)到网格的SelectedItem
的属性. -
ICommand
对于“添加新项目”、“删除所选项目”和“保存对所选项目的更改”。
我的应用程序使用 NHibernate 作为其 ORM 工具,但我不想在整个代码库中泄漏 NHibernate,因此我使用“工作单元”和“存储库”模式将其抽象出来。
这些模式的 NHibernate 特定实现是这样的,即“工作单元”在开始时打开一个新的 NHibernate session 和事务,并在结束时提交事务并处理 session 。因此,工作单元、 session 和事务的生命周期是相同的。工作单元有一个属性 Repository
它使用与工作单元相同的 session 并且具有相同的生命周期。
这是问题所在:
我想填充 Items
MasterDetailViewModel
的构造函数中的集合.目前,我需要创建一个新的工作单元并填充集合。为了没有长时间运行的事务,UoW 将在之后直接处理,同时处理基础 session 。
现在,当用户想要保存对当前项目的更改时,我需要打开另一个 UoW,从数据库中检索实体,用 ItemViewModel
的当前值更新它。 ,将其保存到数据库并处理UoW。
然而,这种方法有几个重要的缺点:
- 我的代码中到处都是
using(var uow = uowFactory.StartNew())
. - 没有进行乐观锁定。如果其他人更改了数据库中的相同项目,他的更改将被默默地覆盖。
- 更新项目需要两次数据库命中,而不是一次。
这让我得出结论,我的 UoW 的实现存在缺陷。
我想过改一下实现,把UoW和Repository的关系倒过来。这意味着 IoC 会将 Repository 注入(inject) ViewModel 而不是 UnitOfWorkFactory。 Repository 现在在功能上等同于 NHibernate 的 ISession
.存储库可以启动一个新的 UoW,它现在与数据库事务相同。
这适用于我的主/细节场景,但它不支持通常用作工作单元同义词的“业务事务”概念,例如跨越多个数据库事务和用户请求的逻辑事务。
问题是:如何最好地实现 Unit of Work 和 Repository 这两种模式以在两种情况下都可用?
最佳答案
改变开始业务交易的地方并不一定会改变其粒度。
不确定我是否完全理解您的示例,但我看不出在存储库的每个方法(每次查询持久存储时)中启动一个新的 UoW 与在以下情况下启动一个新的 UoW 在粒度方面有何不同MasterDetailViewModel 填充它的项目,每次保存一个项目时另一个。
但是,正如您建议的那样,我会在 ViewModel 本身中注入(inject)存储库,因为 UoW 具有存储库属性似乎很奇怪 - UoW 不直接操作存储库,而是一些在 UoW 的上下文中使用 Repository 的对象。
除此之外,我认为您几乎已经解决了与短期、细粒度业务交易相关的缺点。您对此无能为力。
不过还有很多其他 session 策略。您会在此 article 中找到一些建议.
另见
What is your session management strategy for NHibernate in desktop applications?
关于c# - 结合 ORM、工作单元和存储库模式的主从 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9686854/