3

これは私の2つのエンティティのセットアップです:

public class Person {
  public Guid Id {get;set;}
  public string Name {get;set;}
}

public class Immortal : Person {
  public string DarkName {get;set;}
}

それらのマッピングは次のようになります。

<class name="Person">
  <id name="Id">
    <generator class="guid.comb"/>
  </id>
  <property name="Name" />

  <joined-subclass name="Immortal">
    <key column='PersonId' />
    <property name="DarkName" />
  </joined-subclass>
</class>

これがセットアップです。2 つのエンティティがあり、一方は他方の結合されたサブクラスです。フォームから任意の数の条件を取得し、適切な条件をクエリに適用して結果を返す検索フレームワークがあります。

この場合、「名前」という単一のフォーム フィールドがあるとします。名前が Person の Name プロパティと一致するかどうかを確認することで、通常の人であろうと特別なクラスの不滅であろうと、すべての人を呼び戻したいのですが、 Immortal の場合、DarkName がフォームで指定されたものと一致する場合も一致としてカウントしたいと思います。

これは私のジレンマです。どうすればよいでしょうか。NHibernate の ICriteria に関して私ができる最善の方法は、Immortal でサブクエリを作成してそこで名前を確認し、ルートの Person ID がそのサブクエリに含まれているかどうかを確認することです。ただし、数万人のテーブルで作業する場合、結果を取得するこの方法は非常に非効率的であり、実際の状況ではリクエストがタイムアウトすることさえあります (30 秒以上)。

Immortal での外部結合でこのフィールドをチェックしたいので、HQL でもこれを行うことにオープンですが、HQL に任意のプロパティの 2 つの異なるエンティティで結合を実行させることはできません。マッピングの直接の関連付けに基づいている必要があることはわかっています。たとえば、これは私が見たいものです

select person from Person person
  outer join Immortal immortal on immortal.PersonId = person.Id
  where
    person.Name = :name or
    immortal.DarkName = :name

あなたはスタックオーバーフローと何を言いますか?

4

1 に答える 1

3

次の条件クエリは、必要な SQL をほぼ正確に生成します。

これは、条件クエリ エンジンの緩さを利用しています。

var list = session.CreateCriteria<Person>()
    .Add( Expression.Disjunction()
        .Add( Expression.Eq( "Name", name ) )
        .Add( Expression.Eq( "ImmortalName", name ) )
        )
    .List<Person>();

次の SQL が生成されます。

SELECT this_.Id             as Id0_0_,
       this_.Name           as Name0_0_,
       this_1_.ImmortalName as Immortal2_1_0_,
       case 
         when this_1_.Id is not null then 1
         when this_.Id is not null then 0
       end as clazz_0_
FROM   person this_
       left outer join immortal this_1_
         on this_.Id = this_1_.Id
WHERE  (this_.Name = 'foo' /* @p0 */
         or this_1_.ImmortalName = 'foo' /* @p1 */)

次のクラス マッピングを使用しました。

<class name="Person" table="person">
    <id name="Id">
        <generator class="identity" />
    </id>
    <property name="Name" />
    <joined-subclass name="Immortal" table="immortal">
        <key column="Id" />
        <property name="ImmortalName" />
    </joined-subclass>
</class>
于 2010-02-21T14:34:27.523 に答える