【问题标题】:Fluent NHibernate NonUniqueObjectException流畅的 NHibernate NonUniqueObjectException
【发布时间】:2013-04-24 23:24:47
【问题描述】:

我有一个父实体,其中包含一组子实体,几乎每次访问该父实体时都需要从 Web 服务进行更新。我想我可以对集合执行 Clear(),然后添加从 Web 服务接收到的实体列表。当我收到的实体的 ID 与我刚刚清除的任何实体的 ID 不同时,它似乎工作正常,但如果任何 ID 相同,我会得到 NonUniqueObjectException。既然我正在清除它们,难道不应该在插入新实体之前将它们删除吗? Id 是否相同有什么关系?

【问题讨论】:

  • 我们可以看看一些代码来看看你尝试了什么吗?

标签: c# nhibernate fluent


【解决方案1】:

即使您的 ID 相同,但对象本身实际上并不相同。您可以通过执行您的对象来验证这一点。手表中的 GetHashCode()。

NHibernate 认为这是一个新的数据库对象并想要插入它。

您需要保留原始对象并将新值复制到其中。

您可以手动复制这些值,逐个属性 - 但我建议您将其设为动态,这样您就不需要为每种对象类型提供方法。

您可以使用反射编写自己的动态方法或使用第三方映射器...试试 AutoMapper https://github.com/AutoMapper/AutoMapper

复制属性时要小心。如果您的 chil 对象有任何其他也被映射的子对象,您将再次遇到同样的问题。

【讨论】:

  • 所以你的意思是我清除的对象仍然存在?所以当我得到具有相同 ID 的新对象时,它会在删除旧对象之前尝试插入它们?我将映射设置为级联删除所有孤儿。我认为这应该确保如果我删除集合中的任何对象,它也会从数据库中删除。
  • 嗨。我看到你在下面解决了你的问题。但是,删除和重新插入似乎有点奇怪 - 但如果它有效,它就有效!只是出于好奇-您是自己生成ID吗?因为我会认为如果您的数据库正在生成您的 ID,那么它会引发错误......它通常不允许您插入具有标识的行,除非您调用了..“SET IDENTITY_INSERT yourTableName ON” (这是 Sql Server 的语法)我会始终确保我正在更新数据,而不是删除和重新插入 - 对我来说似乎更稳定。
  • ID 来自远程 Web 服务,我自己并没有在我的数据库中生成它们。而且您的答案实际上可能更有效,因为如果我只是遍历现有实体并更新而不是仅仅将它们全部吹走然后刷新到数据库然后重新插入并再次访问数据库,这将意味着更少的数据库调用。如果我更新并添加新的,我认为 nhibernate 将在一次旅行中完成所有工作。
【解决方案2】:

clear 方法后,保存父对象。所以它会从数据库和会话中删除孩子。然后添加孩子并再次保存。

【讨论】:

  • 这不起作用。相反,我做了一个flush(),一切都开始工作了。但你的回答不知何故让我有了尝试的想法。谢谢!
  • 在你的映射中启用 Cascade.AllDeleteOrphan() 如果你错过了这个。
【解决方案3】:

在使用 clear() 初始删除子对象后,我必须在重新插入新子对象(可能具有相同的 ID)之前执行 flush()。然后我做了一个保存,一切正常。

【讨论】:

  • 请提供更多信息以了解其工作原理。正是因为 nhiberate 做事的顺序。 SQL 语句按以下顺序发出:1-所有实体插入,以相同的顺序使用 ISession.Save() 保存相应对象,2-所有实体更新,3-所有集合删除,4-所有集合元素删除,更新和插入,5-所有集合插入,6-所有实体删除,以相同的顺序使用 ISession.Delete() 删除相应的对象
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多