【问题标题】:How to write Linq left join with multiple fields where one is case insensitive如何编写具有多个字段的 Linq 左连接,其中一个字段不区分大小写
【发布时间】:2014-08-12 01:44:21
【问题描述】:

将其转换为左连接的首选方法是什么?这是 Linq to Objects(不是 SQL)。

var result = 
(
   from e in entries
   from r in results
   where r.PropertyId == e.PropertyId &&
         e.ValueAsString.Equals(r.Value, StringComparison.InvariantCultureIgnoreCase)
   select new
   {
      Result = r,
      Entry = e
  }
)
.ToList();

问题:可读性与效率之间的权衡。应该尽量避免 ToLowerInvariant()?

【问题讨论】:

  • 你写的是交叉连接,不是左连接
  • 不完全确定您是否需要查询本身或仅比较字符串方面的帮助,但要找到更好的性能方面,您可以运行测试 "abc".Equals("AbC", StringComparison.InvCultIC)"abc".Equals("AbC".ToLowerInv())。当然,您也可以更疯狂地使用测试用例。
  • 我应该提到每个条目只能有 0 或 1 个结果匹配。
  • 我知道这是一个交叉,但我不知道“join”关键字会创建一个内部查找以避免交叉比较(来自用户@Servy)。谢谢。这恰好适用于非常小的集合。

标签: c# linq left-join linq-to-objects


【解决方案1】:

对于左连接,您需要使用DefaultIfEmpty

var result = 
    (
       from e in entries
       from r in results.Where(x => x.PropertyId == e.PropertyId)
                        .Where(x => e.ValueAsString.Equals(x.Value, StringComparison.InvariantCultureIgnoreCase))
                        .DefaultIfEmpty()
       select new
       {
          Result = r,
          Entry = e
      }
    )
    .ToList();

【讨论】:

  • 看起来这会得到正确的答案,但仍然作为嵌套线性搜索执行。仅适用于小型套装。 @Servy 告诉我,使用“join”关键字将在执行期间添加一个内部查找表,因此倾向于这种方式以获得通用答案。
【解决方案2】:

你写的是cross join,而不是left join

var result = 
(
   from e in entries
   join r in results
   let ev=e.ValueAsString.ToLower()
   let rv=r.Value.ToLower()
   on new{e.PropertyId,ev} equals new {r.PropertyId,rv } into lg
   from r in lg.DefaultIfEmpty()
   select new
   {
      Result = r,
      Entry = e
  }
)
.ToList();

【讨论】:

  • 我对此感到困惑,但只会评论我所知道的:r==null?null:r 只是r
猜你喜欢
  • 1970-01-01
  • 2017-04-15
  • 1970-01-01
  • 2015-06-19
  • 2015-10-21
  • 2023-03-23
  • 2021-07-11
  • 1970-01-01
  • 2016-11-12
相关资源
最近更新 更多