Jak stworzyć dynamiczną metodę rozszerzenia LINQ join
Była biblioteka dynamicznych metod rozszerzeń LINQ wydanych jako próbka z Visual Studio 2008. Chciałbym ją rozszerzyć metodą join. Poniższy kod nie powiódł się z wyjątkiem parametru miss match w czasie wykonywania. Gdzie jest problem?
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))
);
}
3 answers
Sam to naprawiłem. Był to błąd przekazujący zbyt wiele parametrów do CreateQuery(... sprawdzam. Wklej poniższy kod do dynamiki.plik cs w klasie DynamicQueryable dla dynamicznej metody rozszerzenia Join. Źródło przykładowego projektu DynamicQuery znajdziesz pod adresem http://code.msdn.microsoft.com/csharpsamples . Smacznego.
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<T> Join<T>(this IQueryable<T> outer, IEnumerable<T> inner, string outerSelector, string innerSelector, string resultsSelector, params object[] values)
{
return (IQueryable<T>)Join((IQueryable)outer, (IEnumerable)inner, outerSelector, innerSelector, resultsSelector, values);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-05 11:36:00
Możesz zainstalować pakiet nuget systemu.Linq.Dynamiczny.Core - https://github.com/StefH/System.Linq.Dynamic.Core
To ma zaimplementowaną metodę join wraz z różnymi innymi metodami pomocniczymi.
Używając tej biblioteki możesz wykonać proste złączenie w następujący sposób
myContext.TableA.Join(myContext.TableB,'Id','TableAId','outer',null)
W selektorze wyników outer
i inner
są słowami kluczowymi dostępnymi do wyniku połączenia.
Użycie klucza o wielu właściwościach i / lub wybranie wyniku z wiele właściwości można wykonać w następujący sposób
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-13 13:42:31
Oto przykładowy kod pokazujący połączenie w wielu kolumnach. Używając datatable i datarows musisz zawsze uzyskać dostęp do pól za pośrednictwem indexera.
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)"
);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-23 07:20:14