【问题标题】:combine join with String.Contains in Linq query在 Linq 查询中将 join 与 String.Contains 结合使用
【发布时间】:2010-11-24 15:48:34
【问题描述】:

我有以下 linq 查询在两个表之间创建左连接:

            var joinResultRows = from leftTable in dataSet.Tables[leftTableName].AsEnumerable()
                             join
                                  rightTable in dataSet.Tables[rightTableName].AsEnumerable()
                                    on leftTable.Field<string>(leftComparedColumnName) equals rightTable.Field<string>(rightComparedColumnName)
                                        into leftJoinedResult
                             select new { leftTable, leftJoinedResult };

我想得到回答这个问题的行: 左列中的字符串值包含右列中的字符串值。

我试过这个:

            var joinResultRows = from leftTable in dataSet.Tables[leftTableName].AsEnumerable()
                             join
                                  rightTable in dataSet.Tables[rightTableName].AsEnumerable()
                                    on leftTable.Field<string>(leftComparedColumnName).Contains(rightTable.Field<string>(rightComparedColumnName)) equals true
                                        into leftJoinedResult
                             select new { leftTable, leftJoinedResult };

但它不起作用,因为在连接的左侧无法识别 rightTable。

如何创建产生 String.Contains 的连接,我是在“where”子句还是在“On”子句中进行包含?

【问题讨论】:

    标签: sql linq string join contains


    【解决方案1】:

    您尝试过 SelectMany 吗?

    var result =
     from left in dataSet.Tables[leftTableName].AsEnumerable()
     from right in dataSet.Tables[rightTableName].AsEnumerable()
     where left.Field<string>(leftComparedColumnName).Contains(right.Field<string>(rightComparedColumnName))
     select new { left, right };
    

    编辑:

    以下应该有预期的效果:

    class ContainsEqualityComparer: IEqualityComparer<string>
    {
        public bool Equals(string right, string left) { return left.Contains(right); }
        public int GetHashCode(string obj) { return 0; }
    }
    
    var result =
        dataSet.Tables[leftTableName].AsEnumerable().GroupJoin(
            dataSet.Tables[rightTableName].AsEnumerable(),
            left => left,
            right => right,
            (left, leftJoinedResult) => new { left = left, leftJoinedResult = leftJoinedResult },
            new ContainsEqualityComparer());
    

    关键比较通过自定义 IEqualityComparer 运行。两行只有在左右的GetHashCode()相同且Equals返回true时才会连接。

    希望对你有帮助。

    【讨论】:

    • +1 for SelectMany - LINQ 仅支持通过键相等对序列中的元素进行配对的“等连接”。
    • selectMany 是我没想到的,谢谢。它确实找到了匹配项,但没有解决我的问题,因为我需要一个 LEFT JOIN 来创建一个新的连接表或至少一个具有两个表的匿名类型 - 左一个表和一个连接表(如我上面的示例)。执行上面的查询后,我使用 leftTable、leftJoinedResult 手动构建了结果表。我可以让 SelectMany 左加入吗?
    • 我相信没有真正的方法可以实现您对 LinQ 和匿名类型的尝试。但是有很多解决方法,我会在上面的帖子中尝试为您解决。
    • 我已经对其进行了更深入的研究,并通过重载 IEqualityComparer 的 GroupJoin 重现了所需的效果。
    【解决方案2】:

    我通过创建 SelectMany (join) 解决了这个问题,左表保存所有记录,如果没有匹配,右表保存 null:

    var joinResultRows = from leftDataRow in dataSet.Tables[leftTableName].AsEnumerable()
                                 from rightDataRow in dataSet.Tables[rightTableName].AsEnumerable()
                                 .Where(rightRow => 
                                     {
                                         // Dont include "" string in the Contains, because "" is always contained
                                         // in any string.                                         
                                         if ( String.IsNullOrEmpty(rightRow.Field<string>(rightComparedColumnName)))
                                             return false;
    
                                         return leftDataRow.Field<string>(leftComparedColumnName).Contains(rightRow.Field<string>(rightComparedColumnName));
    
                                     }).DefaultIfEmpty() // Makes the right table nulls row or the match row
                                  select new { leftDataRow, rightDataRow };
    

    谢谢你的提示:)

    【讨论】:

      猜你喜欢
      • 2021-05-03
      • 1970-01-01
      • 1970-01-01
      • 2013-11-27
      • 1970-01-01
      • 2020-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多