EF LINQ查询具有表达式:预期方法名称 - 如何将表达式传递到EF查询中使用的函数



我的函数应该根据传递给它的表达式和/或lambda从EF LINQ查询中返回不同的信息。

这是我的代码:

public static ObservableCollection<SI> GetDisplayStratsByJurisd(string jurisd, short Year, 
      Expression<Func<string, bool>> lambStat)
    {
        var ctx = new MI_Entities(server, database);
        var strats = from y in ctx.SIset.AsNoTracking()
                     where y.Jurisd == jurisd && y.Year_ID == Year  && lambStat(y.Status)
                     select y;
        return new ObservableCollection<SI>(strats);
    }

编译器给我以下错误:

方法名称预期

如果我改用它:

    public static ObservableCollection<SI> GetDisplayStratsByJurisd(string jurisd, short Year, 
      Expression<Func<string, bool>> lambStat)
    {
        var ctx = new MI_Entities(server, database);
        Func<string, bool> bob = lambStat.Compile();
        var strats = from y in ctx.SIset.AsNoTracking()
                     where y.Jurisd == jurisd && y.Year_ID == Year  && bob(y.Status)
                     select y;
        return new ObservableCollection<SI>(strats);
    }

然后我有一个不同的错误:

LINQ中不支持LINQ表达节点类型" Indoke"

所以,我不确定如何将lambda传递给功能,以便可以在查询中使用。可以做到吗?如果是这样,如何?

,因此您有一些Expression<Func<TSource, bool>>,并且要使用和功能将它们组合到一个Expression<Func<TSource, bool>>中,以便您可以在Entity Framework中使用它。

以linq的方式将其放在linq语句的串联之间。

让我们创建一些扩展功能。

// A function that takes two Expression<Func<TSource, bool>> and returns the AND expression
static Expression<Func<TSource, bool>> AndAlso<TSource> (
    this Expression<Func<TSource, bool>> x,
    Expression<Func<TSource, bool>> y)
{
     // TODO implement
}

用法:

 Expression<Func<Student, bool>> expr1 = student => student.City == "Birmingham";
 Expression<Func<Student, bool>> expr2 = student => student.Gender == Gender.Male;
 Expression<Func<Student, bool>> exprAND = expr1.AndAlso(expr2);
 var brummyMaleStudents = dbContext.Students.Where(exprAnd).Select(...);

让我们实施Andolso

通常是:

.Where(student  => student.City == "Birmingham" && student.Gender == Gender.Male)

输入参数student用作左表达式的输入和正确表达式的输入。我们需要有一些说:

以type Student的一个输入参数,将其放在左表达式中,并在正确的表达式中进行,并在两个布尔返回值之间执行和执行。返回布尔结果。

为此,我们创建了一个从System.Linq.Expressions.ExpressionVisitor派生的类。

此类代表动作:"将学生放在表达式中并进行计算。该计算称为"访问表达式"。表达的输入是一种表达式,访问的结果是另一个表达式:

internal class ReplaceExpressionVisitor : ExpressionVisitor
{
    private readonly Expression oldValue;
    private readonly Expression newValue;
    public ReplaceExpressionVisitor(ParameterExpression oldValue,
                                    ParameterExpression newValue)
    {
        this.oldValue = oldValue;
        this.newValue = newValue;
    }
    public override Expression Visit(Expression node)
    {
        if (node == this.oldValue)
        {   // "my" expression is visited
            return this.newValue;
        }
        else
        {   // not my Expression, I don't know how to Visit it, let the base class handle this
            return base.Visit(node);
        }
    }
}

现在我们创建了可以实现AndoLSO的表达式访问者:

static Expression<Func<TSource, bool>> AndAlso<TSource>(
    this Expression<Func<TSource, bool>> expr1,
         Expression<Func<TSource, bool>> expr2)
{
     // Create one expression that represent expr1 && expr2
     // the input of expr1 is a TSource,
     // the input of expr2 is a TSource,
     // so the input of expr1 && expr2 is a TSource:
     ParameterExpression inputParameter = Expression.Parameter(typeof(TSource));
     // Visit the left part of the AND:
     var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], inputParameter)
     var left = leftVisitor.Visit(expr1.Body);
     // Visit the right part of the AND:
     var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], inputParameter);
     var right = rightVisitor.Visit(expr2.Body);
     // Combine left and right with a binary expression representing left && right:
     var andExpression = Expression.AndAlso(left, right);
     // return the lambda expression that takes one Tsource as input and returns the AND:
     var lambda = Expression.Lambda<Func<TSource, bool>>(andExpression, new[] {parameter});
     return lambda;
}

用法:

 Expression<Func<Student, bool>> expr1 = student => student.City == "Birmingham";
 Expression<Func<Student, bool>> expr2 = student => student.Gender == Gender.Male;
 
 var brummyMaleStudents = dbContext.Students.Where(expr1.AndAlso(expr2));

另一个示例:

IQueryable<int> numbers = Enumerable.Range(0, 100).Asqueryable();
// two expressions: one that filters 0, 2, 4, 6, 8, ...
// and one that filters 0, 3, 6, 9, 12, ...
Expression<Func<int, bool>> exprEvenNumbers = x => x % 2 == 0;
Expression<Func<int, bool>> exprTrifolds = x => x % 3 == 0;
// the AND of these two expressions should filter 0, 6, 12, 18, ...
Expression<Func<int, bool>> exprSixfolds = exprEvenNumbers.AndAlso(exprTrifolds);
// Test this
IQueryable<int> sixfolds = numbers.Where(exprSixfolds);
IEnumerable<int> results = sixfolds.Take(10).AsEnumerable();
foreach (int i in results)
{
    Console.WriteLine(i);
}

这将打印数字0、6、12、18,...

最新更新