将表达式传递给 NHibernate 中的方法会生成“ConstantExpression”类型的对象;无法转换为“LambdaExpression”类型
这个问题在 NHibernate 2 和 3 中都会出现。我有一个类 A,它有一个类 B 的成员集。直接查询类可以很好地执行。但是,当我将涉及类 B 的表达式之一传递到方法中时,出现以下错误:
System.ArgumentException:类型为“System.Linq.Expressions.ConstantExpression”的对象无法转换为类型“System.Linq.Expressions.LambdaExpression” 。
据我所知,我将完全相同的表达式传递给 Any() 方法。但由于某种原因,他们受到不同的对待。我已经做了一些调试,看起来在第一个方法中,表达式被视为 NodeType 'Quote' 的表达式,而第二个方法中的相同表达式似乎被视为 NodeType 'Constant' 的表达式。第二个方法中的表达式的父表达式具有 NodeType 'MemberAccess'。所以看起来表达式树在不同的测试方法中是不同的。我只是不明白为什么以及如何解决这个问题。
涉及的类:
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());
}
}
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: Object of type 'System.Linq.Expressions.ConstantExpression' cannot be converted to type 'System.Linq.Expressions.LambdaExpression'.
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.
Classes involvend:
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; }
}
Sample test code:
[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());
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是一个问题:
需要一个委托 - 你需要一个表达式树,否则 NHibernate 无法参与其中。试试这个:
顺便说一句,由于使用了空格,您的查询很难阅读。我建议您不要:
明确“Any”调用是在 DataFields 上:
我还建议您将参数名称从“where”更改为“whereExpression”或“predicate”之类的名称。无论如何,某种名词:)
This is one problem:
That's taking a delegate - you want an expression tree otherwise NHibernate can't get involved. Try this:
As an aside, your query is hard to read because of your use of whitespace. I would suggest that instead of:
you make it clear that the "Any" call is on DataFields:
I'd also suggest that you change the parameter name from "where" to something like "whereExpression" or "predicate". Some sort of noun, anyway :)
不太确定这是否是正确的解决方案。这个问题感觉像是一个错误,而我的解决方案就像一个解决方法。尽管如此,以下内容对我有用,归结为通过使用给定表达式的主体和参数来构造新表达式来创建给定表达式的“副本”。
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.