NHibernate:使用merge()时未更新子复合id
映射:NHibernate:使用merge()时未更新子复合id,nhibernate,merge,save,parent-child,composite-id,Nhibernate,Merge,Save,Parent Child,Composite Id,映射: <class name="PhoneTypeTest" lazy="false" table="PhoneType"> <cache usage="read-write"/> <id name ="Id" type="Int32" unsaved-value="0"> <generator class="identity"/> </id> <bag name="Resources" tab
<class name="PhoneTypeTest" lazy="false" table="PhoneType">
<cache usage="read-write"/>
<id name ="Id" type="Int32" unsaved-value="0">
<generator class="identity"/>
</id>
<bag name="Resources" table="PhoneTypeResource" lazy="false" cascade="all" inverse="true">
<key column="PhoneTypeId" />
<one-to-many class="PhoneTypeTestResource" not-found="ignore"/>
</bag>
</class>
<class name="PhoneTypeTestResource" lazy="false" table="PhoneTypeResource">
<composite-id class="CCCC.ResourcesCompositeKey, DDDD" name="Id">
<key-property name="OwnerId" column="PhoneTypeId"/>
<key-property name="CultureId"/>
</composite-id>
<property name="Name"/>
</class>
nHib生成的SQL:
-- statement #1
INSERT INTO PhoneType
DEFAULT VALUES
select SCOPE_IDENTITY()
-- statement #2
SELECT phonetypet0_.PhoneTypeId as PhoneTyp1_61_0_,
phonetypet0_.CultureId as CultureId61_0_,
phonetypet0_.Name as Name61_0_
FROM PhoneTypeResource phonetypet0_
WHERE phonetypet0_.PhoneTypeId = 0 /* @p0 */
and phonetypet0_.CultureId = 'en' /* @p1 */
-- statement #3
INSERT INTO PhoneTypeResource
(Name,
PhoneTypeId,
CultureId)
VALUES ('Name' /* @p0 */,
0 /* @p1 */,
'en' /* @p2 */)
-- statement #4
ERROR:
Could not synchronize database state with session
因此,正如您所看到的,问题在于nHib在保存其父项后不会更新子项的复合id,并且保存子项的尝试失败。为什么?如何让nHib更新这些ID?另外,如果我使用SaveOrUpdate()而不是Merge(),它也可以正常工作!!但我必须使用合并。请帮忙 我在保存后手动更新了子ID,这只是nHibernate bug的另一个解决方法。不要使用复合ID,或者更好的解决方案是不要使用nHibernate..我在保存后手动更新了子ID-这只是nHibernate bug的另一个解决方法。不要使用复合ID,或者更好的解决方案是不要使用nHibernate。我遇到了完全相同的问题。在插入之前,我必须对一些帖子进行更新。然后,当我准备插入时,我得到一个错误,该对象已经在使用中 SaveOrUpdate给了我这个错误,ofc Update也给了我这个错误。合并工作正常,但它只保存父对象,而不保存子对象 不过,连接是子对象是负责执行保存(在mapobject中)的对象
HasMany(x => x.Info)
.Cascade.SaveUpdate();
所以我想公平地说,它有点像预期的那样工作
令人恼火的是,如果在父对象上使用SaveOrUpdate,它实际上也会在理解连接时更新子对象。但是如果使用Merge,它根本不理解连接
这里有一些代码
public AlertEntity InsertCapAlerts(AlertEntity capMessage)
{
using (var transaction = _session.BeginTransaction(IsolationLevel.ReadCommitted))
{
var getCap = GetCapAlert(capMessage.Id);
if (getCap != null)
{
InfoEntity infoToSave = capMessage.Infos.FirstOrDefault();
_session.Merge(infoToSave);
_session.Merge(capMessage);
}
else
_session.Save(capMessage);
transaction.Commit();
return capMessage;
}
}
基本上,我所做的是,当我得到我要保存的新capMessage时,我首先检查它是否已经存在于数据库中。如果它不存在,那么很好,只做一个save()。但是如果它确实存在(这里是SaveOrUpdate总是崩溃的地方),那么我只是创建一个新的子记录实例(我们只有一个子记录,因此FirstOrDefault())
第一次尝试时,我刚刚使用Merge将子对象保存到数据库中(因为SaveOrUpdate仍然会由于对象在上一个会话中使用而给我错误,是的,我尝试了session.Clear()和Flush等等)。效果很好,但后来我注意到我的childobject不再指向它的父对象。因此,childobject现在是一个孤儿,在数据库的街道上哭泣。因此,我们需要做的是将父对象ID再次指向子对象
InfoEntity infoToSave = capMessage.Infos.FirstOrDefault();
infoToSave.AlertEntity_id = capMessage.Id;
_session.Merge(infoToSave);
_session.Merge(capMessage);
你为什么要问?因为nHibernate非常可爱,当它运行Merge时,它不会对childrecords(正如我前面提到的,当你运行SaveOrUpdate时)一语道破。所以当你使用Merge时,你必须自己更新所有childpost,并且你必须再次指出父项
如果有人知道更好的解决方案,请告诉我。否则,我希望这个小代码示例在任何方面都能帮助任何人:)我也遇到了同样的问题。在插入之前,我必须对一些帖子进行更新。然后,当我准备插入时,我得到一个错误,该对象已经在使用中 SaveOrUpdate给了我这个错误,ofc Update也给了我这个错误。合并工作正常,但它只保存父对象,而不保存子对象 不过,连接是子对象是负责执行保存(在mapobject中)的对象
HasMany(x => x.Info)
.Cascade.SaveUpdate();
所以我想公平地说,它有点像预期的那样工作
令人恼火的是,如果在父对象上使用SaveOrUpdate,它实际上也会在理解连接时更新子对象。但是如果使用Merge,它根本不理解连接
这里有一些代码
public AlertEntity InsertCapAlerts(AlertEntity capMessage)
{
using (var transaction = _session.BeginTransaction(IsolationLevel.ReadCommitted))
{
var getCap = GetCapAlert(capMessage.Id);
if (getCap != null)
{
InfoEntity infoToSave = capMessage.Infos.FirstOrDefault();
_session.Merge(infoToSave);
_session.Merge(capMessage);
}
else
_session.Save(capMessage);
transaction.Commit();
return capMessage;
}
}
基本上,我所做的是,当我得到我要保存的新capMessage时,我首先检查它是否已经存在于数据库中。如果它不存在,那么很好,只做一个save()。但是如果它确实存在(这里是SaveOrUpdate总是崩溃的地方),那么我只是创建一个新的子记录实例(我们只有一个子记录,因此FirstOrDefault())
第一次尝试时,我刚刚使用Merge将子对象保存到数据库中(因为SaveOrUpdate仍然会由于对象在上一个会话中使用而给我错误,是的,我尝试了session.Clear()和Flush等等)。效果很好,但后来我注意到我的childobject不再指向它的父对象。因此,childobject现在是一个孤儿,在数据库的街道上哭泣。因此,我们需要做的是将父对象ID再次指向子对象
InfoEntity infoToSave = capMessage.Infos.FirstOrDefault();
infoToSave.AlertEntity_id = capMessage.Id;
_session.Merge(infoToSave);
_session.Merge(capMessage);
你为什么要问?因为nHibernate非常可爱,当它运行Merge时,它不会对childrecords(正如我前面提到的,当你运行SaveOrUpdate时)一语道破。所以当你使用Merge时,你必须自己更新所有childpost,并且你必须再次指出父项
如果有人知道更好的解决方案,请告诉我。否则,我希望这个小代码示例在任何方面对任何人都有帮助:)