2011-03-03 2 views
4

の列にプロパティのマッピング: 流暢NHibernateは - 私は、例えば、カップルのテーブルを持って参加しましたテーブル

  • {... ID、名前、ManufacturerId、}

    • 製品メーカー{ Id、Name、...}

    私はProductオブジェクトにManufacturerNameを含めることができます(名前が必要なときにManufacturer全体の行を読み込む必要はありません)。私のProductMapは次のようになっています...

    Table("Product"); 
    Id(x => x.Id, "Id"); 
    Map(x => x.ProductName, "ProductName"); 
    Map(x => x.ManufacturerId, "ManufacturerId"); 
    References(x => x.Manufacturer, "ManufacturerId"); 
    

    ProductオブジェクトのManufacturerNameプロパティに値を設定するには、何を追加する必要がありますか?私はいくつかの種類のJoin()呼び出しを行う必要があると信じていますが、関連するすべてのパラメータを使用してそれを記述する方法を理解するのに問題があります。現在のテーブル(Product)をProduct.ManufacturerId = Manufacturer.IdのManufacturerテーブルに結合し、Manufacturer.Name列を取得してオブジェクトのManufacturerNameプロパティを設定する必要があります。

  • 答えて

    5

    formulaを使用して、メーカー名を動的に取得できると思います。これは洗練されたソリューションではなく、個人的には、必要な列だけを照会する新しいエンティティ(たとえばProductExtraなど)にマップされた別個のSQLビューを使用する方が好みです。ここに私達は行く:

    1. は、Productクラスに
    2. をManufacturerNameプロパティを追加し、あなたのProductMapにその新しいプロパティのマッピング行を追加します。

      Table("Product"); 
      Id(x => x.Id, "Id"); 
      Map(x => x.ProductName, "ProductName"); 
      Map(x => x.ManufacturerId, "ManufacturerId"); 
      Map(x => x.ManufacturerName).Formula("(select m.ManufacturerName from Manufacturer m where m.Id = ManufacturerId)"); 
      
      References(x => x.Manufacturer, "ManufacturerId"); 
      

    は、この情報がお役に立てば幸いです。

    +0

    これは、データベースが選択パラメータ内のサブクエリをサポートしていないOracleのバージョンであるという点を除いて、きれいな解決策に見えます。 (Ugh)ありがとう –

    +0

    これを答えとして受け入れようとしているのは、おそらく99%の人々がこの質問に対する答えを探して来るからです。悲しいことに、私はこれがうまくいかない8年前のOracleデータベースを使用している1%です。 –

    +0

    ああ..はい、私はOracle 9でテストしていたので、それはおそらくそれがそこで動作する理由です。さて、ヘルパーSQLビューを使って、列のサブセットだけを含む新しいエンティティにマップしてから、通常のProductの代わりに使用することができますが、主にシナリオに依存していると思います。 –

    1

    NH結合は難しく、スキーマがサポートしていないことが必要です。たとえば、結合されたテーブルのプライマリキーは、現在のテーブルのプライマリキーと一致します。これは、NHがその効果に対する明示的な制約を作成しない点を除いて、OneToOneマッピングのように多く機能します。これはあなたのマッピングには当てはまらないので(多対1参照のように見えます)、明示的な結合作業を行うことはできません。

    「パススルー」プロパティをマッピングしてみてください。

    public class Product 
    { 
        ... 
    
        public string ManufacturerName 
        { 
         get{return NHibernateUtil.IsInitialized(Manufacturer) 
            ? Manufacturer.Name : manufacturerName;} 
         set{if(NHibernateUtil.IsInitialized(Manufacturer)) 
          Manufacturer.Name = value 
          else 
          manufacturerName = value;} 
        } 
    } 
    
    ... 
    
    //In your mapping: 
    Map(x => x.ManufacturerName, "ManufacturerName"); 
    

    これは、非正規化フィールドとしてProductテーブル上に正規化された製造元の名前を持続します。このフィールドは、Manufacturerテーブルにも存在します。製品を取得すると、製品テーブルからその名前が取得されます。製造元が何らかの理由で遅延初期化された後(あるいは熱心にロードされた)、Manufacturerテーブルから名前を取得すると、Manufacturerレコードの名前をProductに永続させることができます。

    +0

    ええ、それは多対1です。しかし、製品のテーブルには、実際にそれにManufacturerNameを持っていないので、そのメーカーの行が初期化される(あるいは単にマッピングのエラーをスローします)まで、これは常に空白のでしょうか? –

    +0

    あなたは、テーブルにフィールドを追加、または編集可能なビューから製品のレコードを引っ張ってどちらかの必要があると思います。これがORMの欠点です。 NHは単に、あなたが記録のためにそれを頼むときそれをすべてを引っ張って正当化するためにマッピングされてきたものを十分にしたいことを期待し、外に入社マルチテーブルの結果セットを引っ張って、あなたに完全にカスタマイズされたクエリ以外の多くのオプションを与えるものではありませんDB。 – KeithS

    +0

    残念なことに、データベースの改変は問題になりません。私は個別に、単に行全体を毎回つかむのパフォーマンスに対処する必要がありますように見える、またはそれを処理するためにあまりにも多くのですどこに、私が必要とするすべてManufacturerIdsのリストを作成し、それらのすべてから名前だけをつかみますバッチ。助けてくれてありがとう。 –

    関連する問題