2010-11-25 10 views
0

マッピング:NHibernateは:マージを使用した場合、子複合-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" 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を更新しないため、子を保存しようとして失敗するという問題があります。なぜ??これらのIDを更新するにはどうすればよいですか?また、Merge()の代わりにSaveOrUpdate()を使用すると、うまく動作します。しかし、私はマージを使用する必要があります。助けてください!

答えて

3

保存した後、手動で子IDを更新することになりました。これはnHibernateのバグの別の回避策です。複合IDを使用しないでください。より良い解決策でも、nHibernateは使用しないでください。

0

私はまったく同じ問題を抱えていました。私は挿入をする前にいくつかのポストで更新を実行しなければならなかった。その後、私が挿入をしようとしていたとき、オブジェクトがすでに使用されているというエラーが出ました。

SaveOrUpdateが私にそのエラーを通知し、ofcも更新しました。マージは機能しましたが、親オブジェクトだけを保存し、子オブジェクトは保存しませんでした。しかし

接続は、子オブジェクトはので、私は意図したとおり、それはちょっと働き、公平であることを推測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を取得したときに、まずdbに既に存在するかどうかを確認することです。それができない場合は、Save()を実行してください。しかし、それが存在する場合(SaveOrUpdateが常にクラッシュした場合)、子レコードの新しいインスタンスを作成します(FirstOrDefault()のために1つの子しか持たない)。

最初に試したのは、Mergeを使用してChildオブジェクトをdbに保存しただけです(以前のセッションでオブジェクトが使用されているためにSaveOrUpdateがエラーを返すため、session.Clear()とFlush何でないか)。それはpeachyを働かせましたが、その後、私のchild objectはもはやその親を指摘していないことに気付きました。だから、子供オブジェクトは今データベースの通りで泣いている孤児です。だから私たちがやる必要があるのは、Parent IDをもう一度子オブジェクトに向けることです。

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

なぜ尋ねられますか? nHibernateは、マージを実行すると、(前述のようにSaveOrUpdateを実行するときと同じように)子レコードに関するフライング・ダッチを与えません。 Mergeを使用すると、すべての子ポストを自分で更新しなければならず、もう一度親を指摘しなければなりません。

誰かがこれに対するより良い解決策を知っている場合。お知らせください。さもなければ、私はこの小さなコード例がどんな方法であれ誰にでも役立つことを願っています:)

関連する問題