2011-02-04 7 views
3

私はセッションあたりのトランザクションを使用して呼び出す場合:NHibernate:一時インスタンスを保存するときにID IDはどのように更新されますか?

をsession.SaveOrUpdate(エンティティ) が修正:
session.SaveOrUpdateCopy(エンティティ)

..andエンティティですidentity-Id = 0の一時インスタンス。上記の行は、エンティティのIDを自動的に更新し、インスタンスを永続化しますか?それとも取引でそうするべきなのでしょうか?あるいは、私は何とかそれを明示的にコード化しなければならないのですか?

明らかに、データベース行のID(新しい、一時的なもの)は自動生成され、いくつかの数値として保存されますが、ここでは実際のパラメータインスタンスについて説明しています。ビジネスロジックのインスタンスです。


EDIT - 関連問題の、フォローアップ。

マッピング:

public class StoreMap : ClassMap<Store> 
{ 
    public StoreMap() 
    { 
     Id(x => x.Id).GeneratedBy.Identity(); 
     Map(x => x.Name); 
     HasMany(x => x.Staff) // 1:m 
      .Cascade.All();  
     HasManyToMany(x => x.Products) // m:m 
      .Cascade.All() 
      .Table("StoreProduct");  
    } 
} 

public class EmployeeMap : ClassMap<Employee> 
{ 
    public EmployeeMap() 
    { 
     Id(x => x.Id).GeneratedBy.Identity(); 
     Map(x => x.FirstName); 
     Map(x => x.LastName); 
     References(x => x.Store); // m:1 
    } 
} 

public class ProductMap : ClassMap<Product> 
{ 
    public ProductMap() 
    { 
     Id(x => x.Id).GeneratedBy.Identity(); 
     Map(x => x.Name).Length(20); 
     Map(x => x.Price).CustomSqlType("decimal").Precision(9).Scale(2); 
     HasManyToMany(x => x.StoresStockedIn) 
     .Cascade.All() 
     .Inverse() 
     .Table("StoreProduct"); 
    } 
} 

EDIT2

クラス定義:

public class Store 
{ 
    public int Id { get; private set; } 
    public string Name { get; set; } 
    public IList<Product> Products { get; set; } 
    public IList<Employee> Staff { get; set; } 

    public Store() 
    { 
     Products = new List<Product>(); 
     Staff = new List<Employee>(); 
    } 


    // AddProduct & AddEmployee is required. "NH needs you to set both sides before 
    // it will save correctly" 

    public void AddProduct(Product product) 
    { 
     product.StoresStockedIn.Add(this); 
     Products.Add(product); 
    } 

    public void AddEmployee(Employee employee) 
    { 
     employee.Store = this; 
     Staff.Add(employee); 
    } 
} 

public class Employee 
{ 
    public int Id { get; private set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public Store Store { get; set; } 
} 

public class Product 
{ 
    public int Id { get; private set; } 
    public string Name { get; set; } 
    public decimal Price { get; set; } 
    public IList<Store> StoresStockedIn { get; private set; } 
} 

答えて

3

質問があれば、セッションをフラッシュするたびにエンティティがデータベースに保持されます。あなたの(新しい)エンティティを保存するとき、NHibernateはあなたが提供したジェネレータを使ってIDを生成します。

IDジ​​ェネレータは推奨されていません(this post by Ayendeを参照)。 IDジ​​ェネレータを使用すると、データベースにフラッシュしなくても、保存時に新しいエンティティがデータベースに保持されます。これが起こる理由は、NHibernateがエンティティのIDを提供する必要があるためです。エンティティのIDは、データベースへのラウンドトリップを行わなければ実行できません。

「標準」値を使用する場合は、GuidジェネレータやHiLoのようなものを使用することをお勧めします。このようにして、データベースのラウンドトリップを実際に行うことなくエンティティを保存することができます。これにより、より多くのパフォーマンスを向上させることができます(バッチ処理が念頭に置かれます)。

+0

興味深いです。foreachが各アイテムにSaveを呼び出すことでコレクションを保存すると、すべての保存がデータベースにヒットしますか?完全な行はセッションに保存されますか?保存しますか? – bretddog

+0

私はそれをプロファイラで再確認する必要がありますが、それは非常にうまくいくかもしれません。 –

2

私はUNDわかりませんあなたの質問に耳を傾ける。データベースへの実際の保存は、セッションがフラッシュされる(例えば、トランザクションをコミットすることによって)ときに発生します。 SaveOrUpdate()を呼び出すと、エンティティ自体は保存されません。セッションのフラッシュ時にエンティティが保存されることをセッションに通知するだけです。

エンティティのIDがデータベース内のIDフィールドにマッピングされ、マッピングがNHibernateにデータベースによってIDが設定されていると仮定すると、データベースによって設定されたIDはエンティティのIDとして設定されます保存されました。

+0

はい、そうです。コード行のtransaction.Commit()の後、エンティティのIdプロパティはそのセットをデータベース行に反映させますか?私が尋ねる理由は、(私のrepository.SaveOrUpdateメソッドで)コードをトレースすることであり、エンティティのidは常に.Commitの後でも0です。だから、私はそれがいつ設定されるべきかを確かめたいと思った。 – bretddog

+0

コミット後にIDが0の場合は、ジェネレータを正しくマップしませんでした。 –

+0

ありがとう!それはしっかりと確認されて良かった。それは私の他の問題http://stackoverflow.com/questions/4890123/nhibernate-deleting-child-deletes-parentに関連している必要があります。私はこのIdの問題がその問題の原因になると思った。しかし、私はこれが効果であり、原因ではないと仮定します。 Btw; "ジェネレータ"とは、標準のエンティティクラスマッピングを意味しますか?またはISessionFactoryの設定? – bretddog

1

NhibernateはSaveOrUpdate呼び出しの直後にエンティティのIDプロパティを設定します。

+0

セッションスコープが長くなる可能性があるので、それは当てはまります。しかし、まだ私のIDは0です。 – bretddog

+0

あなたはXMLでマッピングしていますか? – Sly

+0

OPのタグでFluentNHibernateが判断します。 – David

0

私が呼び出すことによって保存されて気づいた:

session.SaveOrUpdateCopy(entity); 

イドを更新しません..which。しかし、に変更して:一時エンティティの..theのIdのは更新されます

session.SaveOrUpdate(entity); 

私はおそらくdocumentation (?).. Section 9.4.2は言う誤解:指定されたインスタンスが保存されていない場合、またはデータベースに存在しない場合

SaveOrUpdateCopy(オブジェクトo)...、NHibernateのは、それを保存し、新たに永続としてそれを返します。インスタンス。

それは私だけですか、それは一時オブジェクト(保存されていない)のような音はありません、「は永続としてを返さ」でしょうか?更新されたIDの意味はありませんか?この文を正しく解釈する方法を明確にしてもらえますか?

+0

あなたはそれが何であるかを理解し、それがあなたの状況に当てはまる場合を除き、 'SaveOrUpdateCopy'を使用すべきではありません。デフォルトでは常に 'SaveOrUpdate'を使います。 'SaveOrUpdate'はエンティティインスタンスを保存または更新し、idプロパティが一時的だった場合はそれを更新します。 'SaveOrUpdateCopy'はIDが変更された*新しいオブジェクト*を返します。メソッドを呼び出したオブジェクトは変更されません。 –

関連する問題