Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework 使用OrElse和AndAlso表达式方法的异常_Entity Framework_Linq_Linq To Entities_Linq Expressions_Dynamic Linq - Fatal编程技术网

Entity framework 使用OrElse和AndAlso表达式方法的异常

Entity framework 使用OrElse和AndAlso表达式方法的异常,entity-framework,linq,linq-to-entities,linq-expressions,dynamic-linq,Entity Framework,Linq,Linq To Entities,Linq Expressions,Dynamic Linq,我正在尝试以编程方式构建表达式树 我的输入中有一个条件类列表,其形式如下: public class Filter { public string field { get; set; } public string operator { get; set; } public string value { get; set; } } 当我构建表达式对象时,我用以下方式为每个条件创建一个表达式 foreach ( Filter sf in rules ) { Exp

我正在尝试以编程方式构建表达式树

我的输入中有一个条件类列表,其形式如下:

public class Filter
{
    public string field { get; set; }
    public string operator { get; set; }
    public string value { get; set; }
}
当我构建
表达式
对象时,我用以下方式为每个条件创建一个
表达式

foreach ( Filter sf in rules ) {
    Expression ex = sf.ToExpression( query );
    if ( mainExpression == null ) {
        mainExpression = ex;
    }
    else {
        if ( logicalCondition == "AND" ) {
            mainExpression = Expression.And( mainExpression, ex );
        }
        else if ( logicalCondition == "OR" ) {
            mainExpression = Expression.Or( mainExpression, ex );
        }
    }
}
Filter.ToExpression()方法的实现方式如下

public override Expression ToExpression( IQueryable query ) {
    ParameterExpression parameter = Expression.Parameter( query.ElementType, "p" );
    MemberExpression memberAccess = null;
    foreach ( var property in field.Split( '.' ) )
        memberAccess = MemberExpression.Property( memberAccess ?? ( parameter as Expression ), property );
    ConstantExpression filter = Expression.Constant( Convert.ChangeType( value, memberAccess.Type ) );
    WhereOperation condition = (WhereOperation)StringEnum.Parse( typeof( WhereOperation ), operator );
    LambdaExpression lambda = BuildLambdaExpression( memberAccess, filter, parameter, condition, value );
    return lambda;
}
当我有一个单一条件时,一切都正常,但当我尝试使用
以及
或lse
静态方法之一组合表达式时,我收到一个
invalidooperation异常
,它表示:

未为类型定义二进制运算符或 'System.Func
2[MyObject,System.Boolean]'和
'System.Func
2[MyObject,System.Boolean]'

我有点糊涂了。有人能更好地解释异常的原因并提出解决方案吗


非常感谢

你把
a=>a==3
a=>a==4
组合成
(a=>a==3)| |(a=>a==4)
,但是你应该试着把它变成
a=>(a==3 | | a==4)
。这不是很难手动完成,但是。寻找“组合表达式”

编辑:根据要求,提供了一个如何手动执行此操作的简单示例

编辑2:它使用.NET 4中新增的
ExpressionVisitor
,但是。我假设MSDN代码不符合您的“第三方”要求。您只需将
受保护的虚拟表达式访问(Expression exp)
方法更改为
public
。由于
Enumerable.Zip对您不可用,并且不需要,因此它现在已不存在

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;

namespace DemoApp
{
    <include ExpressionVisitor definition here for .NET 3.5>

    public class ExpressionParameterReplacer : ExpressionVisitor
    {
        public ExpressionParameterReplacer(IList<ParameterExpression> fromParameters, IList<ParameterExpression> toParameters)
        {
            ParameterReplacements = new Dictionary<ParameterExpression, ParameterExpression>();
            for (int i = 0; i != fromParameters.Count && i != toParameters.Count; i++)
                ParameterReplacements.Add(fromParameters[i], toParameters[i]);
        }
        private IDictionary<ParameterExpression, ParameterExpression> ParameterReplacements
        {
            get;
            set;
        }
        protected override Expression VisitParameter(ParameterExpression node)
        {
            ParameterExpression replacement;
            if (ParameterReplacements.TryGetValue(node, out replacement))
                node = replacement;
            return base.VisitParameter(node);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Expression<Func<int, bool>> exprA = a => a == 3;
            Expression<Func<int, bool>> exprB = b => b == 4;
            Expression<Func<int, bool>> exprC =
                Expression.Lambda<Func<int, bool>>(
                    Expression.OrElse(
                        exprA.Body,
                        new ExpressionParameterReplacer(exprB.Parameters, exprA.Parameters).Visit(exprB.Body)),
                    exprA.Parameters);
            Console.WriteLine(exprA.ToString());
            Console.WriteLine(exprB.ToString());
            Console.WriteLine(exprC.ToString());
            Func<int, bool> funcA = exprA.Compile();
            Func<int, bool> funcB = exprB.Compile();
            Func<int, bool> funcC = exprC.Compile();
            Debug.Assert(funcA(3) && !funcA(4) && !funcA(5));
            Debug.Assert(!funcB(3) && funcB(4) && !funcB(5));
            Debug.Assert(funcC(3) && funcC(4) && !funcC(5));
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用系统诊断;
使用System.Linq;
使用System.Linq.Expressions;
命名空间DemoApp
{
公共类ExpressionParameterReplace:ExpressionVisitor
{
公共表达式参数替换器(IList fromParameters,IList TopParameters)
{
ParameterReplacements=新字典();
for(int i=0;i!=fromParameters.Count&&i!=toParameters.Count;i++)
参数替换。添加(从参数[i],到参数[i]);
}
私人索引参数替换
{
得到;
设置
}
受保护的重写表达式VisitParameter(ParameterExpression节点)
{
参数表达替换;
if(ParameterReplacements.TryGetValue(节点,输出替换))
节点=替换;
返回基本访问参数(节点);
}
}
班级计划
{
静态void Main(字符串[]参数)
{
表达式exprA=a=>a==3;
表达式exprB=b=>b==4;
表达式表达式表达式=
Lambda(
奥莱尔斯酒店(
exprA.Body,
新表达式参数replacer(exprB.Parameters,exprA.Parameters)。访问(exprB.Body)),
表达式参数);
Console.WriteLine(exprA.ToString());
Console.WriteLine(exprB.ToString());
Console.WriteLine(exprC.ToString());
Func funcA=exprA.Compile();
Func funcB=exprB.Compile();
Func Func=exprC.Compile();
Assert(funcA(3)&&!funcA(4)&!funcA(5));
Assert(!funcB(3)&funcB(4)&funcB(5));
Assert(funcC(3)&&funcC(4)&&funcC(5));
}
}
}

您好,谢谢您的回答。我不能用第三方代码来解决这个问题。你能更好地解释一下哪种方法是“手工操作”吗?再次感谢@Lorenzo当然,我已经添加了一个基于我用作示例的两个表达式的程序。嗨,我已经尝试实现了你的解决方案。我知道ExpressionVisitor来自LinqKit的源代码,我已经了解了它的工作原理。现在的问题是:
IEnumerable
Zip
方法从何而来?我正在使用.NET 3.5,但找不到该方法:(@Lorenzo啊,我用的是.NET4,它同时带有
ExpressionVisitor
类和
Enumerable.Zip
扩展方法。我会看看我是否也能为3.5版做些工作,但那会有点复杂。@Lorenzo事实证明,MS在MSDN上发布了一个功能性
ExpressionVisitor
,所以我测试了它。)看看它是否有效(它确实有效),并提到它。而且
Enumerable.Zip实际上不是必需的,所以我放弃了它,在它的位置添加了一个简单的
for
循环。