簡體   English   中英

NHibernate:使用merge()時不會更新子組合ID

[英]NHibernate: child composite-id is not updated when using merge()

制圖:

    <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>

實體:

public class PhoneTypeTest
{
    public PhoneTypeTest()
    {
        Resources = new List<PhoneTypeTestResource>();
    }

    public virtual int Id { get; set; }
    public virtual IList<PhoneTypeTestResource> Resources { get; set; }
}

public class PhoneTypeTestResource
{
    public virtual ResourcesCompositeKey Id { get; set; }
    public virtual string Name { get; set; }
}

單元測試:

        var ent = new PhoneTypeTest();
        ent.Resources.Add(new PhoneTypeTestResource { Id = new ResourcesCompositeKey { CultureId = En, OwnerId = 0 }, Name = "Name" });

        Session.Merge(ent);
        Session.Flush();
        Session.Clear();

由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錯誤的另一種解決方法。 不要使用復合ID,或者甚至是更好的解決方案,也不要使用nHibernate。

我有同樣的問題。 在插入之前,我必須對某些帖子進行更新。 然后,當我要插入時,我得到了該對象已在使用中的錯誤。

SaveOrUpdate給了我這個錯誤,並且也提供了更新。 合並工作但它僅保存父對象,而不保存子對象。

不過,連接是子對象是負責執行保存操作的對象(在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將Child對象保存到db中(因為由於該對象在上一個會話中使用,因此SaveOrUpdate仍然會給我錯誤,是的,我確實嘗試了session.Clear()和Flush等等)。 它工作得像桃子,但后來我注意到我的子對象不再指向其父對象。 因此,子對象現在是在數據庫街道上哭泣的孤兒。 因此,我們需要做的是再次將父ID指向子對象。

InfoEntity infoToSave = capMessage.Infos.FirstOrDefault();
infoToSave.AlertEntity_id = capMessage.Id;
_session.Merge(infoToSave);
_session.Merge(capMessage);

你為什么問? 因為nHibernate非常可愛,所以當它運行Merge時,它不會給子記錄帶來麻煩(就像我前面提到的那樣運行SaveOrUpdate時)。 因此,當您使用“合並”時,必須自己更新所有子帖子,並且必須再次指出“父”。

如果有人知道更好的解決方案。 請告訴我。 否則,我希望這個小代碼示例可以以任何方式幫助任何人:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM