将表达式参数作为属性添加到LINQ to Entities中 [英] Adding Expression argument as property in LINQ to Entities

查看:312
本文介绍了将表达式参数作为属性添加到LINQ to Entities中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用EF6,如何将给定的 Expression< Func< Row,string>> 参数绑定到现有的select表达式,而不必重写每个属性绑定使用表达式树?

Using EF6, how would I bind a given Expression<Func<Row, string>> argument to an existing select expression, without having to rewrite every property binding using expression trees?

public IEnumerable<RowModel> GetRowModels(Expression<Func<Row, string>> textExpr)
{
    return from row in MyDatabaseContext.MyTable
           select new RowModel
           {
               RowID = row.ID,
               CreatedDate = row.CreatedDate,
               AnotherProperty = row.AnotherProperty,
               Text = textExpr, // how do I bind this expression?
               Value = row.OtherStuff.Where(os => os.ShouldUse).Select(os => os.Value).FirstOrDefault(),
               AnotherValue = row.OtherStuff.Where(os => os.ShouldUseAgain).Select(os => os.Value).FirstOrDefault()
           };
}


推荐答案

组合几个表达式的方法。具体来说,我们想要的是一种方法来获取映射值的表达式,然后接受接受第一个表达式的输入的表达式和第一个表达式的输出,并计算一个新值。

What you need here is a method to combine several expressions. Specifically, what we would like is a way to take an expression that maps a value and then also accept an expression that accepts the input of the first expression, and the output of the first expression, and computes a new value.

作为这种方法的一个实现,我们可以用第一个函数的主体替换第一个函数的结果的所有实例;之后,所有需要做的是确保两个表达式都使用相同的参数实例。

As an implementation of this method we can replace all instances of "the result of the first function" with the body of the first function; after that all that needs to be done is to ensure that both expressions are using the same Parameter instance.

public static Expression<Func<TFirstParam, TResult>>
    Combine<TFirstParam, TIntermediate, TResult>(
    this Expression<Func<TFirstParam, TIntermediate>> first,
    Expression<Func<TFirstParam, TIntermediate, TResult>> second)
{
    var param = Expression.Parameter(typeof(TFirstParam), "param");

    var newFirst = first.Body.Replace(first.Parameters[0], param);
    var newSecond = second.Body.Replace(second.Parameters[0], param)
        .Replace(second.Parameters[1], newFirst);

    return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param);
}

以下代码用于替换另一个表达式的所有实例: / p>

The following code is used to replace all instances of an expression with another:

public static Expression Replace(this Expression expression,
    Expression searchEx, Expression replaceEx)
{
    return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
internal class ReplaceVisitor : ExpressionVisitor
{
    private readonly Expression from, to;
    public ReplaceVisitor(Expression from, Expression to)
    {
        this.from = from;
        this.to = to;
    }
    public override Expression Visit(Expression node)
    {
        return node == from ? to : base.Visit(node);
    }
}

至于使用该函数;这很简单我们在 textExpression 上调用组合,然后我们可以创建一个lambda,接受行和文本结果第一个表达式为参数。这可以让您编写一个几乎完全像您已经拥有的lambda,但是您可以使用text参数分配 Text 值:

As for using the function; it's simple enough. We call Combine on your textExpression, and then we can create a lambda accepting both the row and the text result of the first expression as parameters. This lets you write a lambda that's almost exactly like the one you already have, but where you can use the text parameter to assign the Text value:

public IEnumerable<RowModel> GetRowModels(
    Expression<Func<Row, string>> textExpr)
{
    return MyDatabaseContext.MyTable.Select(
        textExpr.Combine((row, text) => new RowModel
    {
        RowID = row.ID,
        CreatedDate = row.CreatedDate,
        AnotherProperty = row.AnotherProperty,
        Text = text, // how do I bind this expression?
        Value = row.OtherStuff.Where(os => os.ShouldUse)
            .Select(os => os.Value).FirstOrDefault(),
        AnotherValue = row.OtherStuff.Where(os => os.ShouldUseAgain)
            .Select(os => os.Value).FirstOrDefault()
    }));
}

这篇关于将表达式参数作为属性添加到LINQ to Entities中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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