0

NHibernate を使用して、いくつかの異なるテーブルからパラメーターをフィルター処理し、NHibernate の遅延読み込みを利用できるやや妥当な SQL を生成する検索クエリを作成しようとしています。オンラインでさまざまなヒントを読むと、次のスニペットのように、QueryOver オブジェクトを使用して、使用されているパラメーターを条件付きで追加することが、最新かつ最高の方法のようです。

Hibernate.Criterion.QueryOver<Models.Site, Models.Site> query = NHibernate.Criterion.QueryOver.Of<Models.Site>();

if (!string.IsNullOrEmpty(state))
                query = query.WhereRestrictionOn(r => r.State.StateName).IsInsensitiveLike("%" + state + "%");

if (startDate.HasValue)
                    query = query.Where(r => r.Events
                                            .Where(e=>e.EventDate >= startDate.Value)
                                            .Count() > 0
                                    );

return query.GetExecutableQueryOver(currentSession).Cacheable().List();

(イベントにはサイトへの外部キーがあります)

2 つの質問があります。親オブジェクトだけでなく、子オブジェクトをフィルター処理するにはどうすればよいですか? 上記のサンプル コードでは、一致するイベントを持つすべてのサイトが表示されますが、そのサイト内では、一致するイベントのみが必要です。結合またはサブクエリを使用することになっている場合、どのように使用しますか? 結合またはサブクエリによる遅延読み込みでツリーのような階層を維持することについて混乱しています。

編集:これは回答済みです。ありがとうございます! or 句を追加するにはどうすればよいですか? Disjunction オブジェクトへの参照を見つけましたが、QueryOver メソッドを使用して利用できるようには見えません。

編集: サイト基準でフィルタリングされたサイト (最上位オブジェクト) のリストを作成したいのですが、各サイトには、イベント基準でフィルタリングされたイベントのリストが必要です。

次のような SQL が生成されることを期待しています。

SELECT *
FROM [site] s
    LEFT JOIN [event] e ON s.siteID = e.siteID
WHERE e.eventDate > @eventDate
    AND (s.stateCd = @state OR s.stateName LIKE @state)
4

2 に答える 2

1

そのクエリを次のように実行します。

//use aliases. Optional but more practical IMHO 
Site siteAlias = null;
Event eventAlias = null;

//use JoinAlias instead of JoinQueryOver to keep the condition at the "Site" level
var results = Session.QueryOver(() => siteAlias)
        .JoinAlias(m => m.Event, () => eventAlias)
        .Where(() => eventAlias.EventDate > eventDate)
        .Where(() => siteAlias.StateCd == state || Restrictions.On(() => siteAlias.StateName).IsLike(state))
        .List();

Disjunction クラスについて言及しましたが、実際には次のように QueryOver で使用できます。

var disjunction= new Disjunction();
disjunction.Add(() => siteAlias.StateCD == state);
disjunction.Add(Restrictions.On(() => siteAlias.StateName).IsLike(state));

QueryOver クエリは次のようになります。

var results = Session.QueryOver(() => siteAlias)
        .JoinAlias(m => m.Event, () => eventAlias)
        .Where(() => eventAlias.EventDate > eventDate)
        .Where(disjunction)
        .List();
于 2011-06-01T02:28:38.543 に答える
0

psousa によって提案されているように結合エイリアスを使用すると、オブジェクト構造と行構造の奇妙な組み合わせが得られ、トップレベルのオブジェクトがそれらにアタッチされている子オブジェクトによって複製されます。探していた結果を得るには、次のコードに示すように、TransformUsing と DistinctRootEntityResultTransformer を使用できます。

    Site siteAlias = null;
    Event eventAlias = null;

    var results = currentSession.QueryOver<Site>(() => siteAlias)
            .JoinAlias(m => m.Event, () => eventAlias)
            .Where(() => eventAlias.EventDate > eventDate)
            .Where(() => siteAlias.StateCd == state || Restrictions.On(() => siteAlias.StateName).IsLike(state))
            .TransformUsing(new NHibernate.Transform.DistinctRootEntityResultTransformer())
            .List();
于 2011-06-27T17:24:55.567 に答える