我们正在使用DTO模式将我们的域对象从服务层封送到我们的存储库,然后通过NHibernate下载到数据库。
我遇到了一个问题,我将DTO从存储库中拉出(例如CustomerDTO),然后将其转换为服务层中的域对象(Customer)。然后我尝试将一个新对象保存回来(例如SalesOrder),该对象包含相同的Customer对象。然后将其转换为SalesOrderDTO(和CustomerDTO)以便推入存储库。
NHibernate不喜欢这样 - 它抱怨CustomerDTO是重复记录。我假设这是因为它在同一个会话中撤出了第一个CustomerDTO,并且由于返回已经来回转换,因此无法将其识别为同一个对象。
我被困在这里还是有办法解决这个问题?
由于
詹姆斯
答案 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来解决这个问题。我认为重新附加可能仅在您未在此会话中加载对象时才有效。