问题描述
我在使用NHibernate v3.2.0和以下查询时遇到问题:
I've got problem with NHibernate v3.2.0, and following query:
class DocumentBase {}
class Requisition: DocumentBase {}
class Order: DocumentBase {}
Repository.GetAll<DocumentBase>()
.Where(d => (d is Requisition) && ((Requisition)d).ProductItem != null)
基本查询旨在列出所有文档,但是也可以按类型(和准类型,例如没有产品的文档)过滤此文档.在上面的代码中,只有一个条件,但谓词可能更复杂,例如:
Base query is designed to list all documents, but there is also possibility to filter this documents by type (and quasi-type, which is for example document without product). In code above there is only one condition, but predicate can be more complicated, for ex:
Repository.GetAll<DocumentBase>()
.Where(d =>
((d is Requisition) && ((Requisition)d).ProductItem != null) ||
(d is Order) ||
[...]
)
执行后,我收到消息Invalid path: 'd.ProductItem'
的InvalidPathException
.有任何想法吗?支持吗?
When executed I receive InvalidPathException
with message Invalid path: 'd.ProductItem'
.Any ideas? Is it supported?
到目前为止,我设法通过以下查询来绕过此错误:
So far I managed to bypass this error with following query:
Repository.GetAll<DocumentBase>()
.Where(d =>
(d is Requisition) &&
Repository.GetAll<Requisition>()
.Any(r => r.Id == d.Id && r.ProductItem != null)
)
但是从性能上来说,这绝对不是最好的选择.
But definitely it's not the best choise in terms of performance.
推荐答案
正如有人提到的,可以在NHibernate中扩展Linq provider.这是对我有用的解决方案:
As someone mentioned it is possible to extend Linq provider in NHibernate. Here is solution which worked for me:
public static class OzirNhExtensions
{
// Cast method to use in query
public static TTarget Cast<TTarget>(this Object source)
{
return ((TTarget)source);
}
}
class CastHqlGeneratorForMethod : BaseHqlGeneratorForMethod
{
public CastHqlGeneratorForMethod()
{
this.SupportedMethods = new MethodInfo[] {
ReflectionHelper.GetMethodDefinition(
() => OzirNhExtensions.Cast<Object>(null)
)
};
}
// In here simply skip cast expression
// (it works probably because I have every sub-entity
// in the same table that base entity)
public override HqlTreeNode BuildHql(
MethodInfo method,
Expression targetObject,
ReadOnlyCollection<Expression> arguments,
HqlTreeBuilder treeBuilder,
IHqlExpressionVisitor visitor)
{
return visitor.Visit(arguments[0]).AsExpression();
}
}
查询示例:
Repository.GetAll<DocumentBase>()
.Where(d => d.Cast<Requisition>().ProductItem != null &&
d.Cast<Requisition>().ProductItem.Name == "Something"
)
这篇关于NHibernate + IQueryable访问子类型属性在哪里的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!