usar una tipo sintaxis puede funciones expresiones expresion español delegado cómo convertir consulta aprender anonimas c# linq linq-to-entities entity-framework-6 expression-trees

c# - una - lambda sintaxis



Agregar argumento de Expresión como propiedad en LINQ a Entidades (1)

Lo que necesita aquí es un método para combinar varias expresiones. Específicamente, lo que nos gustaría es una forma de tomar una expresión que mapea un valor y luego también aceptar una expresión que acepte la entrada de la primera expresión y la salida de la primera expresión, y que calcule un nuevo valor.

Como una implementación de este método, podemos reemplazar todas las instancias de "el resultado de la primera función" con el cuerpo de la primera función; después de eso, todo lo que se necesita hacer es garantizar que ambas expresiones utilicen la misma instancia de Parameter .

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); }

El siguiente código se usa para reemplazar todas las instancias de una expresión con otra:

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); } }

En cuanto a usar la función; es lo suficientemente simple Llamamos Combine en su textExpression , y luego podemos crear un lambda que acepte los resultados de fila y texto de la primera expresión como parámetros. Esto le permite escribir una lambda que es casi exactamente igual a la que ya tiene, pero donde puede usar el parámetro de texto para asignar el valor de Text :

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() })); }

Usando EF6, ¿cómo vincularía un argumento determinado de Expression<Func<Row, string>> a una expresión de selección existente, sin tener que reescribir cada enlace de propiedad utilizando árboles de expresión?

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() }; }