我对nHibernate相当陌生,我一直在尝试编写查询。我似乎做不好。我的模型中有一个"产品",其中包含"组件"的ICollection。我需要找到包含组件引用以字母"G"开头的任何组件的所有产品。我试过这个:
var matching = session.QueryOver<Product>()
.JoinQueryOver<Component>(p => p.Components)
.Where(c => c.ComponentReference.StartsWith("G")).List();
但是,我收到一个编译错误,说"委托系统.Func>>不接受 1 个参数。
JoinQueryOver上有一个重载,我可以在其中传递表达式>>
所以我本以为我的查询会起作用,因为 ICollection 实现了 IEnumerable。
我已经尝试了各种其他方法使用.演员和加入别名,但它们似乎只是不必要的复杂。
谁能指出我哪里出错了?
提前致谢
,我建议使用子查询。它可能看起来像这样
Product product = null;
Component component = null;
// the subselect, returning the Product.ID
// only if the Component.ComponentReference is like G%
var subQuery = QueryOver.Of<Component>(() => component)
.WhereRestrictionOn(() => component.ComponentReference)
.IsLike("G", MatchMode.Start)
.Select(c => c.Product.ID);
// the root Product
var query = session.QueryOver<Product>(() => product)
.WithSubquery
.WhereProperty(() => product.ID)
.In(subQuery);
// and finally the list
var list = query
.List<Product>();
生成的 SQL 如下所示:
SELECT product
FROM product
WHERE productId IN (SELECT ProductId FROM Component WHERE ComponenentReferece LIKE 'G%')
为什么使用子查询而不是 JOIN? 因为在这种情况下,连接会产生 Carthesian 乘积。返回的产品集将乘以以 G% 开头的所有组件
子查询将产生纯粹的、扁平的产品集,因此我们可以正确地对它使用分页 ( .Take()
.Skip()
)