cor*_*ore 3 nhibernate queryover
在连接到另一个表之后,我遇到了同一个对象的多个实例的小问题.为了测试我创建一个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
Run Code Online (Sandbox Code Playgroud)
我甚至认为这种行为是正确的,但我如何防止多个实例?是否可以在查询中?
只是为了获取信息,为什么我需要进行这种不必要的连接:我想根据不同的标准来扩展查询,类似于:
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();
Run Code Online (Sandbox Code Playgroud)
在这里,我遇到了不同的问题,具体取决于标准.
尝试Transformers.DistinctRootEntity在您的场景中使用以消除笛卡尔积.
Product productAlias = null;
var query = _session.QueryOver<Store>()
.JoinAlias(s => s.Products, () => productAlias)
query = query.TransformUsing(Transformers.DistinctRootEntity);
var result = query.List();
Run Code Online (Sandbox Code Playgroud)
我们将解决方案分成两个查询.
QueryOver<Store>()将正确返回一个不同的列表.而且,根据设计,它将支持分页(Take(),Skip()).结果SQL将如下所示
SELECT ... // top one
FROM Store
WHERE StoreID IN ( SELECT StoreID ...) // inner one
Run Code Online (Sandbox Code Playgroud)
让我们从内部选择开始,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));
}
Run Code Online (Sandbox Code Playgroud)
一旦我们过滤了商店,我们就可以在前一个中使用这个子查询
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>();
Run Code Online (Sandbox Code Playgroud)
现在我们可以将任何过滤器应用于内部查询,并获得满足过滤条件的商店ID列表...同时使用顶级查询,这是不同的...