1
我正在使用Castle ActiveRecord和NHibernate。使用HQL查找匹配关系的行
我有一个实例类与组件类具有多对多的关系。我想找到与特定组件组件相关的实例。这可能在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()));
但它看起来像在只有一个项目与一组,也不能一组与一组。
编辑:
这是我能做的最好的:
IQueryable<Instance> q = Queryable;
foreach(var c in components) {
q = q.Where(i => i.Components.Contains(c));
}
但是,这是非常低效的。它为每个where子句的SQL查询添加一个子选择。那是一次非常冗长的斟酌。它加入实例表,实例/组件连接表和组件表。它只需要实例/组件连接表。
由于数据的性质,我将实施混合解决方案。缩小查询中的实例,然后使用linq到对象以在需要时获取正确的实例。 代码如下所示:
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();
任何人都有更好的方法吗?
您确定这是否行?我很确定Contains只包含一个对象,而不是一个列表。 ActiveRecord自带一个不允许的Linq提供程序。我也检查了nhcontrib中的NHibernate.Linq,它在那里也不起作用。 – oillio 2010-09-28 15:51:40
@oillio:我的错误,我很抱歉。不过,我已经编辑过该代码的帖子,以便比较一个列表是否包含另一个列表,后面是http://bit.ly/aQSE31。但是,我不是100%,它会与NHibernate.Linq一起工作。 – rebelliard 2010-09-28 16:02:02
该版本比我上面的linq代码好得多。不幸的是,它不会与NHibernate一起工作。 – oillio 2010-09-28 16:23:37