3

他のテーブルに結合した後、同じオブジェクトの複数のインスタンスで小さな問題が発生します。テストのために、2つで1つを作成しますStoreProductsManyToMany-Relation)。次のスニペットは、うまくいけば私の問題を説明しています。

var preResult = _session.QueryOver<Store>().List(); // One store

Product productAlias = null;
var result = _session.QueryOver<Store>()
    .JoinAlias(s => s.Products, () => productAlias)
    .List();                                        // Two instances of the same store

この動作は正しいと思いますが、どうすれば複数のインスタンスを防ぐことができますか?クエリ内で可能ですか?


この不要な結合を行う必要がある理由については、次のように、さまざまな基準に従ってクエリを拡張したいと思います。

Product productAlias = null;
var query = _session.QueryOver<Store>().JoinAlias(s => s.Products, () => productAlias);
if (!string.IsNullOrWhiteSpace(criteria.ProductName))
{
    query.Where(Restrictions.On(() => productAlias.Name).IsInsensitiveLike(criteria.ProductName));
}

if (criteria.ProductType != null)
{
    query.Where(s => productAlias.Type == criteria.ProductType);
}

var result = query.List();

ここで、基準に応じてさまざまな問題が発生しました。

4

2 に答える 2

6

Transformers.DistinctRootEntityシナリオで使用して、デカルト積を削除してみてください。

Product productAlias = null;
var query = _session.QueryOver<Store>()
                    .JoinAlias(s => s.Products, () => productAlias)

query = query.TransformUsing(Transformers.DistinctRootEntity);

var result = query.List();
于 2012-12-29T00:33:49.773 に答える
5

ソリューションを2つのクエリに分割しましょう。

  1. 一番上のものQueryOver<Store>()は、明確なリストだけを正しく返します。さらに、設計上、ページング(Take()Skip())をサポートします。
  2. 内側のものは、ストアIDのリストだけを返します。これは、あらゆる基準を完全に満たしています...

結果のSQLは次のようになります

SELECT ... // top one 
FROM Store
WHERE StoreID IN ( SELECT StoreID ...) // inner one

内側

内側の選択、NHibernateデタッチから始めましょうQueryOver

Store storeAlias = null;
Product productAlias = null;

// detached query, resulting in a set of searched StoreID 
var subQuery = QueryOver.Of<Store>(() => storeAlias)
    .JoinAlias((s) => s.Products, () => productAlias)
    .Select((s) => s.ID); // ID projection

if (!string.IsNullOrWhiteSpace(criteria.ProductName))
{
    subQuery.Where(Restrictions.On(() => productAlias.Code)
        .IsInsensitiveLike(criteria.ProductName));
}

ストアをフィルタリングしたら、このサブクエリを上位のサブクエリで使用できます

var query = session.QueryOver<Store>()
   // IN clause
   .Where(Subqueries.PropertyIn("ID", subQuery.DetachedCriteria))
   .Skip(100) 
   .Take(50) // paging over already distinct resultset
   ;

var result = query.List<Store>();

これで、内部クエリに任意のフィルターを適用し、フィルター基準を満たすストアIDのリストを取得できます...異なるトップクエリを操作している間...

于 2012-12-29T08:44:01.623 に答える