2

我们使用 DTO 模式将我们的域对象从服务层编组到我们的存储库中,然后通过 NHibernate 下放到数据库中。

我遇到了一个问题,我从存储库中提取了一个 DTO(例如 CustomerDTO),然后将其转换为我的服务层中的域对象(客户)。然后我尝试保存一个包含相同客户对象的新对象(例如 SalesOrder)。这又被转换为 SalesOrderDTO(和 CustomerDTO)以推送到存储库中。

NHibernate 不喜欢这样 - 它抱怨 CustomerDTO 是重复记录。我假设这是因为它在同一个会话中取出了第一个 CustomerDTO,并且由于返回已经来回转换,它无法将其识别为同一个对象。

我被困在这里还是有办法解决这个问题?

谢谢

詹姆士

4

4 回答 4

2

您可以使用 Lock 将对象重新附加到 NHibernate 中的会话 - 例如

_session.Lock(myDetachedObject, NHibernate.LockMode.None);

这可能有帮助,也可能没有帮助,具体取决于这里发生的事情。附带说明一下,将 DTO 与 NHibernate 一起使用并不是最常见的做法,NHibernate(大部分)支持持久性无知这一事实意味着 DTO 通常不像其他一些 ORM 框架那样广泛使用。

于 2009-05-14T08:28:05.653 回答
2

这实际上是关于 NHibernate 会话如何工作的。因此,如果您在会话中拉取 CustomerDTO 的实例,然后过一段时间您应该获得相同的 CustomerDTO(例如通过主键) - 实际上您将获得对与您在第一次检索中所做的完全相同的对象的引用。

因此,您要做的是通过调用 session.Merge 合并对象,或者通过调用 session.Get(primaryKey) 向会话请求对象进行更新并刷新会话。

然而,正如史蒂夫所建议的那样——这通常不是你所做的——你真的想从数据存储中获取你的域对象并使用 DTO(如果需要)将数据传输到 UI、Web 服务等等......

于 2009-05-14T09:02:51.420 回答
2

正如其他人所指出的,实现 Equals 和 GetHashCode 是朝着正确方向迈出的一步。还可以查看 NHibernate 对“附加”OR/M 习语的支持。

您还可以使用nosetter.camelcase 选项:http: //davybrion.com/blog/2009/03/entities-required-properties-and-properties-that-shouldnt-be-modified/

此外,我想鼓励您不要被网上信息的缺乏所劝阻。这并不意味着你疯了,或者做错了事。这只是意味着您正在处理边缘情况。不幸的是,像 NHibernate 这样的库的最大消费者是小型的内部和/或 Web 应用程序,它们可以自由地将所有持久性需求依赖于单个数据库。实际上,这条规则有很多例外。

例如,我目前正在开发一个商业桌面应用程序,其中我的一个域对象的数据分布在 SQL CE 数据库和磁盘上的图像文件之间。不幸的是,NHibernate 只能帮助我处理 SQL CE 持久性。我被迫使用一种“双重映射”(参见Martin Fowler 的“企业应用程序体系结构的模式”)通过存储库层映射我的域模型,该存储库层知道哪些数据进入 NHibernate 以及哪些数据进入磁盘。

它发生了。这是一个真正的需要。有时,明显缺乏工具表明您采用了错误的方法。但有时事实是,您确实处于边缘情况,需要为自己构建一些这些模式来完成它。

于 2009-06-03T18:38:34.487 回答
1

我假设这是因为它在同一个会话中取出了第一个 CustomerDTO,并且由于返回已经来回转换,它无法将其识别为同一个对象。

你说的对。休眠不能。考虑实现 Equals 和 Hashcode 来解决这个问题。我认为重新附加可能仅在您尚未在此会话中加载对象时才有效。

于 2009-05-14T18:23:48.420 回答