3

在连接到另一个表后,我对同一对象的多个实例有一个小问题。为了测试,我Store用两个创建一个Products(ManyToMany-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

让我们将解决方案分成两个查询。

  1. 前一个QueryOver<Store>()将正确返回一个不同的列表。更重要的是,通过设计它将支持分页(Take(), Skip())。
  2. 内部的,将只返回一个商店 ID 列表,它完全符合任何标准......

结果 SQL 将如下所示

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

让我们从内部选择开始,NHibernate detached 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 回答