NHibernate + IQueryable访问子类型属性在哪里 [英] NHibernate + IQueryable access subtype property in where

查看:81
本文介绍了NHibernate + IQueryable访问子类型属性在哪里的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用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访问子类型属性在哪里的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆