NHibernate,DTO和NonUniqueObjectException

时间:2009-05-14 08:01:26

标签: nhibernate dto

我们正在使用DTO模式将我们的域对象从服务层封送到我们的存储库,然后通过NHibernate下载到数据库。

我遇到了一个问题,我将DTO从存储库中拉出(例如CustomerDTO),然后将其转换为服务层中的域对象(Customer)。然后我尝试将一个新对象保存回来(例如SalesOrder),该对象包含相同的Customer对象。然后将其转换为SalesOrderDTO(和CustomerDTO)以便推入存储库。

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

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

由于

詹姆斯

4 个答案:

答案 0 :(得分:2)

您可以使用Lock - 例如

将对象重新附加到NHibernate中的会话
_session.Lock(myDetachedObject, NHibernate.LockMode.None);

这可能会有所帮助,也可能没有帮助,具体取决于这里发生的事情。另外,使用DTO和NHibernate不是最常见的做法,NHibernate(大多数)支持持久性无知的事实意味着通常DTO不像其他ORM框架那样广泛使用。

答案 1 :(得分:2)

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

所以你要做的就是通过调用session.Merge来合并对象,或者通过调用session.Get(primaryKey)来询问你的会话对象,然后进行更新并刷新会话。

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

答案 2 :(得分:2)

正如其他人所说,实施Equals和GetHashCode是朝着正确方向迈出的一步。另请参阅NHibernate对“附加”OR / M习语的支持。

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

此外,我想鼓励你不要被在线缺乏信息所劝阻。这并不意味着你疯了,或做错了。这只是意味着你在一个边缘案件中工作。不幸的是,像NHibernate这样的图书馆的最大消费者是内部和/或网络应用程序都很小,可以自由地将所有持久性需求都放在单个数据库上。实际上,这条规则有很多例外。

例如,我目前正在开发一个商业桌面应用程序,其中我的一个域对象的数据分布在SQL CE数据库和磁盘上的图像文件之间。不幸的是,NHibernate只能帮助我解决SQL CE持久性问题。我被迫使用一种“双映射”(参见Martin Fowler's "Patterns of Enterprise Application Architecture")通过存储库层映射我的域模型,该存储库层知道NHibernate的数据和磁盘的内容。

它发生了。这是一个真正的需要。有时,工具明显缺乏表明你采取了不好的方法。但有时事实是,你真的处于边缘地位,需要为自己建立一些这样的模式来完成它。

答案 3 :(得分:1)

  

我认为这是因为它   拉出了第一个CustomerDTO   同一个会议,因为   返回已被转换回来   它不能认识到这一点   相同的对象。

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