c# - 结合 ORM、工作单元和存储库模式的主从 View

标签 c# .net nhibernate design-patterns architecture

我不确定如何最好地结合 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。
然而,这种方法有几个重要的缺点:

  1. 我的代码中到处都是using(var uow = uowFactory.StartNew()) .
  2. 没有进行乐观锁定。如果其他人更改了数据库中的相同项目,他的更改将被默默地覆盖。
  3. 更新项目需要两次数据库命中,而不是一次。

这让我得出结论,我的 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?

What should be the lifetime of an NHibernate session?

关于c# - 结合 ORM、工作单元和存储库模式的主从 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9686854/

相关文章:

.net 二进制格式化程序反序列化定义已发生很大变化的对象

c# - 在 C# 中寻找一个简单的独立持久字典实现

nhibernate - 工作单元实现

nhibernate - 如何使用 Fluent-nhibernate 将集合计数映射到实体

mysql - 将 NHibernate SchemaUpdate 与 MySQL 一起使用时出现问题 - 没有错误,但没有任何反应!

c# - 正确结束SoundEffectInstance

c# - 如何将 DataGridViewCellStyle 恢复为其继承值

c# - asp.net MVC 模型绑定(bind)一个字节数组

C#/Sqlite 将查询结果存储为变量的简单方法

c# - 如何在 LINQ-to-Entities 查询中使用自定义属性?