将表达式传递给 NHibernate 中的方法会导致“ConstantExpression"类型的对象无法转换为“LambdaExpression"类型 [英] Passing an expression to a method in NHibernate results in Object of type 'ConstantExpression' cannot be converted to type 'LambdaExpression'

查看:29
本文介绍了将表达式传递给 NHibernate 中的方法会导致“ConstantExpression"类型的对象无法转换为“LambdaExpression"类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题发生在 NHibernate 2 和 3 中.我有一个类 A,它有一个类 B 的成员集.直接查询类执行得很好.但是,当我将涉及 B 类的表达式之一传递给方法时,出现以下错误:

This problem occurs in both NHibernate 2 and 3. I have a Class A that has a member set of class B. Querying the classes directly executes nicely. But when I pass one of the expressions involving class B into a method I get the following error:

System.ArgumentException:System.Linq.Expressions.ConstantExpression"类型的对象无法转换为System.Linq.Expressions.LambdaExpression"类型.

System.ArgumentException: Object of type 'System.Linq.Expressions.ConstantExpression' cannot be converted to type 'System.Linq.Expressions.LambdaExpression'.

据我所知,我将完全相同的表达式传递给 Any() 方法.但由于某种原因,他们受到了不同的对待.我已经进行了一些调试,看起来在第一种方法中,表达式被视为具有 NodeType 'Quote' 的表达式,而第二种方法中的相同表达式似乎被视为具有 NodeType 'Constant' 的表达式.第二种方法中表达式的父表达式具有 NodeType 'MemberAccess'.所以看起来表达式树在不同的测试方法中是不同的.我只是不明白为什么以及如何解决这个问题.

As far as I can see I am passing the exact same expression into the Any() method. But for some reason they are treated differently. I have done some debugging and it looks like in the first method, the expression is treated as an expression with NodeType 'Quote', while the same expression in the 2nd method seems to be treated as an expression with NodeType 'Constant'. The parent expression of the expression in the 2nd method has a NodeType 'MemberAccess'. So it looks like the expression tree is different in the different test methods. I just don't understand why and what to do to fix this.

涉及的类:

public class A
{
   public virtual int Id { get; set; }
   public virtual ISet<B> DataFields { get; set; }
}

public class B
{
   public virtual int Id { get; set; }
}

示例测试代码:

    [TestMethod]
    public void TestMethod1()
    {
        using (ISession session = sessionFactory.OpenSession())
        {
            var records = session.Query<A>()
                                 .Where<A>(a => a.DataFields
                                                 .Any(b => b.Id == 1));
            Console.Write("Number of records is {0}", records.Count());
        }
    }

    [TestMethod]
    public void TestMethod2()
    {
        GetAsWhereB(b => b.Id == 1);
    }

    private void GetAsWhereB(Func<B, bool> where) 
    {
        using (ISession session = sessionFactory.OpenSession())
        {
            var records = session.Query<A>()
                                 .Where(a => a.DataFields
                                              .Any(where));
            Console.Write("Number of records is {0}", records.Count());
        }
    }

推荐答案

不太确定这是否是正确的解决方案.这个问题感觉就像一个错误,我的解决方案就像一个解决方法.尽管如此,以下内容对我有用,归结为通过使用其主体和参数来构造一个新表达式来创建给定表达式的副本".

Not quite sure if this is the proper solution or not. The problem feels like a bug and my solution like a workaround. Nonetheless the following works for me, which boils down to creating a 'copy' of the given expression by using its body and parameter to construct a new expression.

private void GetAsWhereB(Func<B, bool> where) 
{
    Expression<Func<T, bool>> w = Expression.Lambda<Func<T, bool>>(where.Body, where.Parameters);
    using (ISession session = sessionFactory.OpenSession())
    {
        var records = session.Query<A>()
                             .Where(a => a.DataFields
                                          .Any(w));
        Console.Write("Number of records is {0}", records.Count());
    }
}

这篇关于将表达式传递给 NHibernate 中的方法会导致“ConstantExpression"类型的对象无法转换为“LambdaExpression"类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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