Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何创建动态LINQ连接扩展方法_Linq_Linq To Sql_C# 3.0_Linq To Entities_Linq To Objects - Fatal编程技术网

如何创建动态LINQ连接扩展方法

如何创建动态LINQ连接扩展方法,linq,linq-to-sql,c#-3.0,linq-to-entities,linq-to-objects,Linq,Linq To Sql,C# 3.0,Linq To Entities,Linq To Objects,有一个动态扩展方法库,作为一个示例发布。我想用join方法扩展它。以下代码在运行时因参数未匹配异常而失败。问题在哪里 public static IQueryable Join(this IQueryable outer, IEnumerable inner, string outerSelector, string innerSelector, string resultsSelector,

有一个动态扩展方法库,作为一个示例发布。我想用join方法扩展它。以下代码在运行时因参数未匹配异常而失败。问题在哪里

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

我现在自己修好了。向CreateQuery(…)调用传递太多参数是一个小学生错误。将以下代码粘贴到动态联接扩展方法的DynamicQueryable类中的Dynamic.cs文件中。您可以在找到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);
    }
公共静态IQueryable联接(此IQueryable外部、IEnumerable内部、字符串外部选择器、字符串内部选择器、字符串结果选择器、参数对象[]值)
{
如果(inner==null)抛出新的ArgumentNullException(“inner”);
如果(outerSelector==null)抛出新的ArgumentNullException(“outerSelector”);
如果(innerSelector==null)抛出新的ArgumentNullException(“innerSelector”);
如果(resultsSelector==null)抛出新的ArgumentNullException(“resultsSelector”);
LambdaExpression outerSelectorLambda=DynamicExpression.ParseLambda(outer.ElementType,null,outerSelector,value);
LambdaExpression innerSelectorLambda=DynamicExpression.ParseLambda(inner.AsQueryable().ElementType,null,innerSelector,values);
ParameterExpression[]参数=新的ParameterExpression[]{
Expression.Parameter(outer.ElementType,“outer”)、Expression.Parameter(inner.AsQueryable().ElementType,“inner”)};
LambdaExpression resultsSelectorLambda=DynamicExpression.ParseLambda(参数,null,结果选择器,值);
返回outer.Provider.CreateQuery(
表情,打电话(
类型(可查询),“加入”,
新类型[]{outer.ElementType,inner.AsQueryable().ElementType,outerSelectorLambda.Body.Type,resultsSelectorLambda.Body.Type},
Expression,inner.AsQueryable().Expression,Expression.Quote(outerSelectorLambda),Expression.Quote(innerSelectorLambda),Expression.Quote(resultsSelectorLambda));
}
//通用重载。
公共静态IQueryable联接(此IQueryable外部、IEnumerable内部、字符串外部选择器、字符串内部选择器、字符串结果选择器、参数对象[]值)
{
返回(IQueryable)联接((IQueryable)外部,(IEnumerable)内部,外部选择器,内部选择器,结果选择器,值);
}

以下是一些示例代码,显示了多列上的联接。使用datatable和datarows,您需要始终通过索引器访问字段

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

您可以安装System.Linq.Dynamic.Core-

这使得join方法与其他各种helper方法一起实现

使用此库,您可以按以下方式进行简单连接

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

在结果选择器中,外部和内部是访问联接结果的关键字

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


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

您能粘贴准确的错误消息吗?您能发布一个使用Join的示例吗。我很想用它,但我在LINQ是个新手。谢谢。嘿,你知道这本书吗?我在2018年的“实体框架核心的现代数据访问”中发现了它。用法示例如下:此代码的简单用法如下:
var result=myDbContext.Person.Join(myDbContext.Roles),“new(Id作为firstKey,SomeOtherId作为secondKey)”,“new(PersonId作为firstKey,AlternativeId作为secondKey)”,“new(PersonId作为firstKey,AlternativeId作为secondKey)”(内部为r,外部为p);
请注意,如果它在多个列上连接,如果它们的名称不相同,则必须使用“as[somekey]”,否则将发生错误。此外,在结果选择器中,您还可以使用关键字“outer”和“inner”如果我想在Join中比较不区分大小写的字符串,该如何实现?如果我的表数也是动态的,该如何实现?这并不能回答问题。这里您使用的是Linq提供的Join方法,问题是关于创建此方法,因为Linq尚未提供该方法。