如果调用ToList或ToArray,为什么C#编译器允许在表达式树中使用动态操作

如果调用ToList或ToArray,为什么C#编译器允许在表达式树中使用动态操作,c#,lambda,expression,ienumerable,iqueryable,C#,Lambda,Expression,Ienumerable,Iqueryable,请注意:我知道这里讨论的主要错误消息有很多相关信息,但我找不到任何讨论我问题的帖子。 因此,请仔细阅读,然后再将其标记为副本 像往常一样,如果你能指出一个讨论我所困惑的问题的问题,我很乐意把这个问题记下来 我有一个方法返回一个IQueryable,如下所示 public IQueryable<dynamic> GetData(DateTime Start, DateTime End, Nullable<int> EmployeeId = null) { var

请注意:我知道这里讨论的主要错误消息有很多相关信息,但我找不到任何讨论我问题的帖子。

因此,请仔细阅读,然后再将其标记为副本

像往常一样,如果你能指出一个讨论我所困惑的问题的问题,我很乐意把这个问题记下来


我有一个方法返回一个IQueryable,如下所示

public IQueryable<dynamic> GetData(DateTime Start, DateTime End, Nullable<int> EmployeeId = null)
{
    var query = from T1 in Context.Table1
                join T2 in Context.Table2
                on T1.Col1 equals T2.Col1
                join T3 in Context.Table3
                on T2.Col1 equals T3.Col1
                where T1.Col1 == EmployeeId
                        && T1.Col2 >= Start
                        && T1.Col2 <= End
                select new
                {
                    Value1 = T1.Col1,
                    Value2 = T2.Col5,
                    Value3 = T3.Col7

                };

    return query;
}
这给了我下面的编译器错误

表达式树不能包含动态操作

令人困惑的部分:

如果在调用Sum()之前添加.ToList()或.ToArray(),则不会出现此编译器错误

我知道.ToList()或.ToArray()将查询具体化(在本例中是从数据库中获取数据),并生成IEnumerable而不是IQueryable,但为什么C编译器允许我在这里的表达式中使用动态操作?


注意:C#的版本是4.0(.net4.0)

在第一种情况下,您调用的是IQueryable.Sum

public static int Sum<TSource>(this IQueryable<TSource> source,
                                    Expression<Func<TSource, int>> selector)
public static int Sum(此IQueryable源,
表达式选择器)
在第二种情况下,您调用的是IEnumerable.Sum

 public static int Sum<TSource>(this IEnumerable<TSource> source,
                                     Func<TSource, int> selector)
public static int Sum(此IEnumerable源代码,
Func选择器)

因此,在第一种情况下,编译器尝试从lambda表达式创建表达式树,但由于您使用的是dynamic,所以无法创建表达式树。

在第一种情况下,您调用的是IQueryable.Sum

public static int Sum<TSource>(this IQueryable<TSource> source,
                                    Expression<Func<TSource, int>> selector)
public static int Sum(此IQueryable源,
表达式选择器)
在第二种情况下,您调用的是IEnumerable.Sum

 public static int Sum<TSource>(this IEnumerable<TSource> source,
                                     Func<TSource, int> selector)
public static int Sum(此IEnumerable源代码,
Func选择器)

因此,在第一种情况下,编译器尝试从lambda表达式创建表达式树,但由于您使用的是dynamic,因此无法创建表达式树。

您可能需要了解更多有关
Func
表达式之间的区别的信息。前一种情况下没有表达式树。@IvanStoev谢谢。遗憾的是,我没有注意到两个Sum方法接受不同的参数。没有问题,伙计,这种情况经常发生:)通常避免在返回可查询项的方法中使用
dynamic
和匿名类型。一个简单的结果类(又称DTO)将使您免于麻烦。您可能需要进一步了解
Func
Expression
之间的区别。前一种情况下没有表达式树。@IvanStoev谢谢。遗憾的是,我没有注意到两个Sum方法接受不同的参数。没有问题,伙计,这种情况经常发生:)通常避免在返回可查询项的方法中使用
dynamic
和匿名类型。一个简单的结果类(又称DTO)将使您免于麻烦。