Linq中的区别仅基于表的一个字段

Meg*_*ain 114 c# sql linq

我试图在Linq中使用.distinct来获取基于表的一个字段的结果(因此不需要表中的整个重复记录).

我知道使用distinct来编写基本查询,如下所示:

var query = (from r in table1
orderby r.Text
select r).distinct();
Run Code Online (Sandbox Code Playgroud)

但我需要r.text不重复的结果.

Dan*_*rth 270

试试这个:

table1.GroupBy(x => x.Text).Select(x => x.FirstOrDefault());
Run Code Online (Sandbox Code Playgroud)

这将对表进行分组Text并使用每个组中的第一行,从而得到Text不同的行.

  • 我不得不使用FirstOrDefault,否则就会出现运行时错误 (5认同)
  • @ user585440:在这种情况下,你使用如下的匿名类型:`table1.GroupBy(x => new {x.Text,x.Property2,x.Property3}).选择(x => x.First()) ;` (4认同)
  • @TruthOf42 这不太可能。`GroupBy` 不会创建空组,请参阅我之前的评论。很可能,您的代码包含的内容比您在此处看到的要多。也许您也有“Where”或“First”的条件。 (4认同)
  • 如果 groupby 有超过 1 个字段怎么办? (2认同)
  • 是的,你说得对,我已经找到了.不管怎么说,还是要谢谢你.我还发现Select(x => x.First())会导致崩溃.最好更改为Select(x => x.FirstOrDefault()); (2认同)

Ser*_*rvy 23

MoreLinq有一个DistinctBy方法,您可以使用:

它可以让你做到:

var results = table1.DistictBy(row => row.Text);
Run Code Online (Sandbox Code Playgroud)

该方法的实现(缺少参数验证)如下:

private static IEnumerable<TSource> DistinctByImpl<TSource, TKey>(IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
    HashSet<TKey> knownKeys = new HashSet<TKey>(comparer);
    foreach (TSource element in source)
    {
        if (knownKeys.Add(keySelector(element)))
        {
            yield return element;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 好吧,如果我错了,请纠正我,但这里的区别是在内存中完成,而不是在DB中完成?这不能导致意外的全扫描吗? (9认同)

Tim*_*ter 12

但我需要r.text不重复的结果

听起来好像你想要这个:

table1.GroupBy(x => x.Text)
      .Where(g => g.Count() == 1)
      .Select(g => g.First());
Run Code Online (Sandbox Code Playgroud)

这将选择Text唯一的行.


小智 9

上面 Daniel Hilgarth的回答导致了Entity-FrameworkSystem.NotSupported异常。使用Entity-Framework,它必须是:

table1.GroupBy(x => x.Text).Select(x => x.FirstOrDefault());
Run Code Online (Sandbox Code Playgroud)


TKh*_*ili 7

更新

从 .NET 6 开始,引入了新的DistinctBy运算符。然而,虽然这对于 Linq to Objects 效果很好,但似乎不适用于 Linq to Entities。我使用 EF Core 6.0.6 和 SQL Server 对其进行了测试。

一般来说,LINQ 运算符成对出现以支持这两种情况。例如,Enumerable.Select涵盖 Linq to Objects,Queryable.Select涵盖 Linq to Entities。

有趣的DistinctBy是,也有这两种风格,但 EF Core 的 SQL Server 提供程序不支持将其转换为 SQL。在我看来,原因是这会导致查询速度变慢。

原答案

围绕这个话题有很多讨论。

您可以在这里找到其中之一:

最流行的建议之一是采用 lambda 表达式作为参数的 Distinct 方法,正如 @Servy 所指出的。

C# 的首席架构师 Anders Hejlsberg在这里提出了解决方案。还解释了为什么框架设计团队决定不添加采用 lambda 的 Distinct 方法的重载。