2008-12-23 85 views
9

有一个动态LINQ扩展方法库作为Visual Studio 2008的示例发布。我想用连接方法来扩展它。下面的代码在运行时失败并出现参数未命中匹配异常。哪里有问题?如何创建动态LINQ连接扩展方法

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

你能粘贴确切的错误信息做什么? – Perpetualcoder 2008-12-23 19:55:55

+0

你可以发布一个使用你的加入的例子。我想使用它,但是我在LINQ中是一个新手。谢谢。 – joe 2011-02-02 03:05:19

回答

19

我已经自己修复了。在CreateQuery(...)调用中传递了太多参数是一个男生错误。将以下代码粘贴到DynamicQueryable类中的Dynamic.cs文件中,以获取动态Join扩展方法。您可以在http://code.msdn.microsoft.com/csharpsamples找到DynamicQuery示例项目的源代码。
享受。

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

使用示例在这里:http://stackoverflow.com/questions/5996403/counting-percent-of-rows-with-category-out-of-total-number-of-rows-using-dynamic/6047324#6047324 – alpav 2011-05-18 19:01:45

1

以下是一些示例代码,显示多列上的连接。使用数据表和数据行需要始终通过索引器访问字段。

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)" 
    ); 
2

您可以安装System.Linq.Dynamic.Core的NuGet包 - https://github.com/StefH/System.Linq.Dynamic.Core

这与其他各种辅助方法一起实施的连接方法。

使用这个库,你可以做一个简单的在结果选择outerinner以下方式

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

加入是访问的连接结果的关键词。

使用具有多个属性和/或选择具有多个属性结果的密钥可以通过以下方式

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)