2012-03-05 5 views
4

これは私を夢中にしています。コレクションのうちの1つをクラスに保存することはできますが、もう一方は保存することはできません。私のクラスは1つのコレクションをデータベースに保存し、他のコレクションは保存しないのはなぜですか?

私はかなり同じですこれらの2つの方法がありますCategory

public Category() 
{ 
    Items = new List<Item>(); 
    Prices = new List<Price>(); 
} 

というクラスを持っています。コンストラクタは、Categoryというプロパティと、それぞれNameおよびPriceというプロパティを設定します。

public virtual Item AddItem(string name) 
{ 
    var item = new Item(this, name); 
    Items.Add(item); 
    return item; 
} 

public virtual Price AddPrice(decimal price) 
{ 
    var price = new Price(this, price); 
    Prices.Add(price); 
    return price; 
} 

マッピング

public class CategoryMap : ClassMap<Category> 
{ 
    public CategoryMap() 
    { 
     // Other properties 

     HasMany(x=>x.Items).Cascade.AllDeleteOrphan(); 
     HasMany(x=>x.Prices).Cascade.AllDeleteOrphan(); 
    } 
} 

あなたが見ることができるように、2つのコレクションは、まったく同じ方法でマッピングされています。 PriceItemの両方のための

マップは、これらの2程度のほとんどすべてが同一である、私の知る限り同じマッピングに

References(x=>x.Category); 

を持っています。ここに問題があります

category.AddItem(someName); 
session.Save(category); // Works 

category.AddPrice(somePrice); 
session.Save(category); // Doesn't work 

これらは、私がテストデータベースを作成するために使用するファイルです。アイテムを保存すると正常に動作します。価格を節約することはできません。クラスとマッピングは同じです。私はそれを理解することはできません。

マッピングが直接コンストラクタを呼び出すよう正常に動作する必要がありますが

session.Save(new Price(category, 1)); 

はなぜカテゴリのコレクションや他のないを保存しない正常に動作しますか?私はプロファイラを走らせました、クラスは価格コレクションを保存しようとしていません。

更新:ゲイブはコメントで指摘するように価格が項目の前に呼び出されるように、私は電話を交換する場合

、価格はデータベースに入り、項目にはありません。

すべてのコレクションの更新後にsession.Flush()と電話しても問題ありません。私はこれをやらなければならないのでしょうか、それとも動くようにマッピングを修正する方法がありますか?

+2

コールの順序を入れ替えると(最初に価格を付けてからItemを追加する)、同じ動作になりますか? –

+0

@GabeMoothart、まあそれは驚くべきことです。最初の呼び出しだけが保存されているように見えます。私がそれらを交換すれば、価格は節約され、商品はそうしない。呼び出しの後に 'session.Flush();'を呼び出そうとしましたが、 'ID列を更新できませんCategoryId' – Brandon

+0

@GabeMoothart、nevermind。そのエラーは、別のマッピングの問題に関連していました。あなたは答えとしてあなたのコメントを投稿できますか? session.flushは機能しますが、すべてのコレクションの更新後に呼び出すはずですか、それとも私のマッピングを修正する方法があるので教えてもらえますか? – Brandon

答えて

1

Priceマッピングで実際に問題が発生しているかどうか、または2番目の呼び出しが失敗したことが問題であるかどうかを確認するには、呼び出しの順序を入れ替える(最初に価格を追加してから項目を追加する)ようにしてください。 flushについて

- あなたが明示的にflushを呼び出す必要はありませんほとんどの時間、それは(details here)する必要があるときにNHibernateは、バックグラウンドで行いますものです。フラッシュモードはマッピングの問題ではありません(設定できるセッションプロパティですが、通常はこれを行う必要はありません)。

トランザクションでコードをラップする場合は、flushは不要です。あなたがいない場合は、あなたがする必要があり、あなたの問題かもしれません。

using (var tx = Session.BeginTransaction()) { 

    category.AddItem(someName); 
    category.AddPrice(somePrice); 
    session.Save(category); 

    tx.Commit(); 
} 

更新:私はあなたの問題は何であったか知っていると思います。あなたのコードが与えられたら、新しいcategoryオブジェクトを作成し、それにデータを設定するように見えます。最初のSave()では、nHibernateは、category_idを子コレクションに割り当てることができないので、自動フラッシュを行います。これは、データベースから取得するまでです。しかし、2回目の周回では、categoryにIDがあるため、セッションをすぐにフラッシュする必要はありません。 nHibernateは、そうである必要がない場合、データベースとのチャットはしません。上記のように、ソリューションは常にトランザクションを使用して、あなたが何をやったのかを指定することです。

+0

ありがとう、ガベ。コードをトランザクションにリファクタリングする方法を見ていきますが、今はFlushを明示的に呼び出すことができます。 – Brandon

+0

categoryが(セッションから取得された)永続オブジェクトである場合、 'session.Save'を呼び出す必要はありません。トランザクションをコミットするだけで済みます。 –

関連する問題