1

次のクラスを想定します。

public class A
{
  public virtual ind Id { get; set; }
  public virtual int Number { get; protected set; }
}

public class B : A
{
  public virtual string SomeValue { get; set; }

  public virtual int BookingNumber
  {
    get { return Number; }
    set { Number = value; }
  }
}

public class C : A
{
  public virtual string SomeOtherValue { get; set; }

  public virtual int AccountNumber
  {
    get { return Number; }
    set { Number = value; }
  }
}

ご覧のとおり、プロパティ Number を別の名前で公開したいと考えています。

次に、A、B、C をマッピングします。

public class AMap : ClassMap<A>
{
  public AMap()
  {
    Id(x => x.Id);
    Map(x => x.Number);
  }
}

public class BMap : SubclassMap<B>
{
  public BMap()
  {
    Map(x => x.SomeValue);
  }
}

public class CMap : SubclassMap<C>
{
  public CMap()
  {
    Map(x => x.SomeOtherValue);
  }
}

このマッピングを使用すると、データをデータベースに保存できます。

ただし、BまたはCにクエリを実行すると:

Session.QueryOver<B>().Where(x => x.BookingNumber).List();

エラーが表示されるcould not resolve property: BookingNumber of: B

私は何を間違っていますか?

4

1 に答える 1

2

なにが問題ですか?マップされていないプロパティでクエリを作成します。

(異なる名前を持つ派生クラスの基本プロパティをラップするのは少なくとも奇妙です)、一部の上位層が同じプロパティに異なる名前を必要とするため、このアプローチが本当に必要な場合...それなら、まあ、わかりました。ただし、NHibernate には別の情報セットを提供する必要があります。

クエリは、SQL ステートメントに変換するのに十分な情報を含む自己記述的な情報と考えてください。

したがって、使用する場合QueryOver<B>.Where(x => x.BookingNumber == 1)...。情報は次のとおりです(ラムダ式を解析する場合):

  1. C# オブジェクトの操作B
  2. そのプロパティを見つけBookingNumber
  3. マップされた表現を見つけます: 列名BookingNumberColumn,
  4. 値をとります:1そして
  5. クエリを作成しましたWHERE BookingNumberColumn = 1

この場合、ステップ番号 3 は失敗します。列がマップされていませんBookingNumber...

解決策は、少なくともデータ(NHibernate)レイヤーで、基本クラスのAマッピングに基づいてフィルターを適用することです

Session
  .QueryOver<B>()
  .Where(x => x.Number == 1) // use the A.Number MAPPED property
  .List<B>();

しかし、私の経験に基づいて、私たちが主に行っていることは、永続性の違い (異なる ID 列名、異なるコード列) を変換し、それらを共通の単純化された構造を持つ C# 基本クラスまたはインターフェイスにマップすることです。

詳細はこちら: 16. QueryOver クエリ

于 2013-02-07T04:54:13.847 に答える