【发布时间】:2010-09-28 01:37:19
【问题描述】:
我正在使用 Castle ActiveRecord 和 NHibernate。
我有一个 Instance 类,它与 Component 类具有多对多关系。我想找到与一组特定组件相关的实例。这在 HQL(或 NHibernate 中的其他任何东西)中是否可行?
这个函数的 linq 版本是:
public Instance find(IEnumerable<Component> passed_components)
{
return Instance.Queryable.Single(i => passed_components.All(x => i.Components.Contains(x)));
}
NHibernate linq 实现当然不能处理这个问题。
我可以编写 HQL 来为其中一个组件执行此操作:
Instance.FindOne(new DetachedQuery("from Instance i where :comp in elements(i.Components)").SetParameter("comp", passed_components.First()));
但是看起来in只比较一个项目和一个集合,它不能比较一个集合和一个集合。
编辑:
这是我能做的最好的:
IQueryable<Instance> q = Queryable;
foreach(var c in components) {
q = q.Where(i => i.Components.Contains(c));
}
但这是非常低效的。它为每个 where 子句添加一个子选择到 SQL 查询中。一个不必要的长子选择。它连接实例表、实例/组件连接表和组件表。它只需要实例/组件连接表。
由于我的数据的性质,我将实施一个混合解决方案。缩小查询中的实例,然后在必要时使用 linq to 对象来获取正确的实例。 代码如下所示:
IQueryable<Instance> q = Queryable;
foreach(var c in components.Take(2)) {
q = q.Where(i => i.Components.Contains(c));
}
var result = q.ToArray();
if(result.Length > 1) {
return result.SingleOrDefault(i => !components.Except(i.Components).Any());
}
else return result.FirstOrDefault();
谁有更好的方法?
【问题讨论】:
标签: nhibernate hql