Come creare un metodo di estensione di join LINQ dinamico

C’era una libreria di metodi di estensioni LINQ dinamici rilasciati come esempio con Visual Studio 2008 . Mi piacerebbe estenderlo con un metodo di join. Il codice seguente non riesce con un’eccezione di corrispondenza di errore del parametro in fase di esecuzione. Dov’è il problema?

public static IQueryable Join(this IQueryable outer, IEnumerable inner, string outerSelector, string innerSelector, string resultsSelector, params object[] values) { if (inner == null) throw new ArgumentNullException("inner"); if (outerSelector == null) throw new ArgumentNullException("outerSelector"); if (innerSelector == null) throw new ArgumentNullException("innerSelector"); if (resultsSelector == null) throw new ArgumentNullException("resultsSelctor"); LambdaExpression outerSelectorLambda = DynamicExpression.ParseLambda(outer.ElementType, null, outerSelector, values); LambdaExpression innerSelectorLambda = DynamicExpression.ParseLambda(inner.AsQueryable().ElementType, null, innerSelector, values); ParameterExpression[] parameters = new ParameterExpression[] { Expression.Parameter(outer.ElementType, "outer"), Expression.Parameter(inner.AsQueryable().ElementType, "inner") }; LambdaExpression resultsSelectorLambda = DynamicExpression.ParseLambda(parameters, null, resultsSelector, values); return outer.Provider.CreateQuery( Expression.Call( typeof(Queryable), "Join", new Type[] { outer.ElementType, inner.AsQueryable().ElementType, outerSelectorLambda.Body.Type, innerSelectorLambda.Body.Type, resultsSelectorLambda.Body.Type }, outer.Expression, inner.AsQueryable().Expression, Expression.Quote(outerSelectorLambda), Expression.Quote(innerSelectorLambda), Expression.Quote(resultsSelectorLambda)) ); } 

L’ho riparato da solo ora. È stato un errore di scolaro passare troppi parametri alla chiamata CreateQuery (…). Incolla il seguente codice nel file Dynamic.cs all’interno della class DynamicQueryable per un metodo di estensione Join dinamico. Puoi trovare l’origine per il progetto di esempio di DynamicQuery su http://code.msdn.microsoft.com/csharpsamples .
Godere.

  public static IQueryable Join(this IQueryable outer, IEnumerable inner, string outerSelector, string innerSelector, string resultsSelector, params object[] values) { if (inner == null) throw new ArgumentNullException("inner"); if (outerSelector == null) throw new ArgumentNullException("outerSelector"); if (innerSelector == null) throw new ArgumentNullException("innerSelector"); if (resultsSelector == null) throw new ArgumentNullException("resultsSelctor"); LambdaExpression outerSelectorLambda = DynamicExpression.ParseLambda(outer.ElementType, null, outerSelector, values); LambdaExpression innerSelectorLambda = DynamicExpression.ParseLambda(inner.AsQueryable().ElementType, null, innerSelector, values); ParameterExpression[] parameters = new ParameterExpression[] { Expression.Parameter(outer.ElementType, "outer"), Expression.Parameter(inner.AsQueryable().ElementType, "inner") }; LambdaExpression resultsSelectorLambda = DynamicExpression.ParseLambda(parameters, null, resultsSelector, values); return outer.Provider.CreateQuery( Expression.Call( typeof(Queryable), "Join", new Type[] {outer.ElementType, inner.AsQueryable().ElementType, outerSelectorLambda.Body.Type, resultsSelectorLambda.Body.Type }, outer.Expression, inner.AsQueryable().Expression, Expression.Quote(outerSelectorLambda), Expression.Quote(innerSelectorLambda), Expression.Quote(resultsSelectorLambda))); } //The generic overload. public static IQueryable Join(this IQueryable outer, IEnumerable inner, string outerSelector, string innerSelector, string resultsSelector, params object[] values) { return (IQueryable)Join((IQueryable)outer, (IEnumerable)inner, outerSelector, innerSelector, resultsSelector, values); } 

È ansible installare il pacchetto nuget di System.Linq.Dynamic.Core – https://github.com/StefH/System.Linq.Dynamic.Core

Questo ha il metodo di join implementato insieme a vari altri metodi di supporto.

Usando questa libreria puoi fare un semplice join nel modo seguente

myContext.TableA.Join(myContext.TableB,'Id','TableAId','outer',null)

nel selettore dei risultati outer e inner sono parole chiave per accedere al risultato del join.

L’uso di una chiave con più proprietà e / o la selezione di un risultato con più proprietà può essere fatto nel modo seguente

myContext.TableA.Join(myContext.TableB,'new (Id as key1,Code as key2)','new (TableAId as key1,AnotherCol as key2)','new(outer.Id,inner.Desc)',null)

Ecco alcuni esempi di codice che mostrano un join su più colonne. Utilizzando datatable e datarows è necessario accedere sempre ai campi tramite l’indicizzatore.

  DataTable t1 = new DataTable(); t1.Columns.Add("FundId", typeof(int)); t1.Columns.Add("Date", typeof(DateTime)); t1.Columns.Add("CodeA", typeof(string)); t1.Rows.Add(1, new DateTime(2010, 01, 01), "A1"); t1.Rows.Add(2, new DateTime(2010, 01, 01), "A2"); t1.Rows.Add(3, new DateTime(2010, 01, 01), "A3"); DataTable t2 = new DataTable(); t2.Columns.Add("FundId", typeof(int)); t2.Columns.Add("Date", typeof(DateTime)); t2.Columns.Add("CodeB", typeof(string)); t2.Rows.Add(1, new DateTime(2010, 01, 01), "B1"); t2.Rows.Add(2, new DateTime(2010, 01, 01), "B2"); t2.Rows.Add(3, new DateTime(2010, 01, 01), "B3"); IQueryable outerTable = t1.AsEnumerable().AsQueryable(); IEnumerable innerTable = t2.AsEnumerable(); var query = outerTable.Join ( innerTable, "new(get_Item(0) as FundId, get_Item(1) as Date)", "new(get_Item(0) as FundId, get_Item(1) as Date)", "new(outer.get_Item(0) as FundId, outer.get_Item(2) as CodeA, inner.get_Item(2) as CodeB)" );