【问题标题】:Linq to Entities Select DistinctLinq to Entity Select Distinct
【发布时间】:2012-11-15 05:46:18
【问题描述】:

我不确定我错过了什么,但我整个下午都在为这个而烦恼。

我有一个公司的 Sql Server 视图,如下所示:

CompanyId varchar(30) NOT NULL
CompanyName varchar(100) NOT NULL
CompanyPriority int NULL
ConfigItem int NOT NULL

使用看起来有点像这样的数据:

00001 | Company One | 99 | 123
00001 | Company One | 99 | 456
00001 | Company One | 99 | 789
00002 | Company Two | 99 | 123
00002 | Company Two | 99 | 456

我正在尝试获取一份不同的公司列表。我要执行的 sql 查询是

select distinct CompanyId, CompanyName,CompanyPriority from vwCompany

这给了我我想要的结果

00001 | Company One | 99
00002 | Company Two | 99

但在我的一生中,我找不到产生这个 sql 的 LINQ 查询,或者任何产生相同结果的东西。

我发现的所有问题都使用分组,它在我的单元测试中运行良好,但在针对实际数据库执行时无法返回不同的结果。

编辑:

所以到目前为止,我已经根据答案尝试了一些事情。

Dim data = _miRepository.GetCompanies().
  Select(Function(c) New With {
           .companyId = c.CompanyId,
           .companyName = c.CompanyName,
           .companyPriority = c.CompanyPriority
         }
       ).Distinct().ToList()

生成sql

SELECT 
1 AS [C1], 
[Extent1].[CompanyId] AS [CompanyId], 
[Extent1].[CompanyName] AS [CompanyName], 
[Extent1].[CompanyPriority] AS [CompanyPriority]
FROM (SELECT 
      [vwCompany].[CompanyId] AS [CompanyId], 
      [vwCompany].[CompanyName] AS [CompanyName], 
      [vwCompany].[CompanyPriority] AS [CompanyPriority], 
      [vwCompany].[CiId] AS [CiId]
      FROM [dbo].[vwCompany] AS [vwCompany]) AS [Extent1]

其中根本没有 distinct 运算符 :(

是的,我在 VB.NET 中这样做只是为了更难找到好的示例:\

编辑 2:

我正在尝试在 VB 中尽可能接近 Eric Js 的答案。

Dim data = (From c In _miRepository.GetCompanies()
            Select New With {.companyId = c.CompanyId,
                             .companyName = c.CompanyName,
                             .companyPriority = c.CompanyPriority
                            }
                          ).Distinct().ToList()

给我

SELECT 
1 AS [C1], 
[Extent1].[CompanyId] AS [CompanyId], 
[Extent1].[CompanyName] AS [CompanyName], 
[Extent1].[CompanyPriority] AS [CompanyPriority]
FROM (SELECT 
      [vwCompany].[CompanyId] AS [CompanyId], 
      [vwCompany].[CompanyName] AS [CompanyName], 
      [vwCompany].[CompanyPriority] AS [CompanyPriority], 
      [vwCompany].[CiId] AS [CiId]
      FROM [dbo].[vwCompany] AS [vwCompany]) AS [Extent1]

仍然没有找到不同的关键字:(

也许我缺少 VB.NET 中的细微差别。

编辑 3:

为了继续这个应用程序的其余部分,我暂时放弃了,并在问题开始时使用 sql 语句创建了一个新视图 (vwDistinctCompanies)。

如果有人设法让这个在 VB.NET 中针对 Sql 视图工作,请告诉我。很明显为什么这在 LINQ 中会如此困难,我不知道:(

【问题讨论】:

  • 以防万一您仍在尝试,我自己尝试了多个查询以及其他用户的不同查询。 @Eric J. 的答案似乎是给了我使用 DISTINCT 关键字的 SQL 语句。当我通过 C# 运行它们时,我不知道如何将其转换为 VB
  • 感谢您的尝试。我无法让他们中的任何一个做出不同的查询。我不确定是因为它是在 VB 中,还是因为它是针对视图而不是表格。
  • 嘿,我进行了进一步的查询。看看我编辑的答案。希望对您有所帮助。

标签: vb.net entity-framework linq-to-entities distinct


【解决方案1】:

-已编辑:-

忽略我之前提到的所有代码(结束编辑部分之后的所有内容)。我尝试了进一步的测试。插入下面的 VB 代码,告诉我你得到了什么结果:

(From c In ctx.Companies Select New With { _
    Key .companyId = c.CompanyId, _
    Key .companyName = c.CompanyName, _
    Key .companyPriority = c.CompanyPriority _
}).Distinct()

我使用 LINQPad 对它们进行了测试,得到了以下 SQL:

SELECT DISTINCT [t0].[CompanyId] AS [companyId],
                [t0].[CompanyName] AS [companyName],
                [t0].[CompanyPriority] AS [companyPriority]
FROM [Companies] AS [t0]

-END EDIT-

几天前我遇到了这个问题。这就是我最终要做的。

您要查找的内容需要您在帖子中提到的 GroupBy 子句。仅使用 Distinct 不会像您期望的那样工作(据我所知)。以下 lambda 表达式是我所做的,紧随其后的是通过 lambda 代码生成的 SQL 语句。

Lambda 代码:

Companies.GroupBy(c => new {
                           c.CompanyId,
                           c.CompanyName,
                           c.CompanyPriority
                       })
         .Select(p => new {
                          CompanyId = p.Key.CompanyId,
                          CompanyName = p.Key.CompanyName,
                          CompanyPriority = p.Key.CompanyPriority
                      })

SQL 代码:

SELECT [t0].[CompanyId] AS [companyId],
       [t0].[CompanyName] AS [companyName],
       [t0].[CompanyPriority] AS [companyPriority]
FROM [Companies] AS [t0]
GROUP BY [t0].[CompanyId],
         [t0].[CompanyName],
         [t0].[CompanyPriority]

【讨论】:

  • 奇怪的是它在 LinqPad 中有效,但在我的应用程序中无效。我想知道这是否是因为它针对 ObjectSet 上的 IQuerable,或者它是否只是该项目所针对的 EF 版本。不幸的是,我在中途被选中,以报道正在休假的原始开发人员。当我有一点喘息的空间时,我会回到这个(我有 2 小时的时间,直到 sprint 审查,我现在需要一些工作:\)。
【解决方案2】:

那不应该是两张桌子吗?一个与

00001 | Company One | 99
00002 | Company Two | 99

还有一个

00001 | 123
00001 | 456
00001 | 789
00002 | 123
00002 | 456

哪个更规范化并且会让您的查询变得非常简单?

【讨论】:

  • 是的,应该,不幸的是,这个决定不在我的掌控之中:(
【解决方案3】:
var query = from c in context.vwCompany
            group c by new { 
                c.CompanyId, 
                c.CompanyName, 
                c.CompanyPriority } into g
            select g.Key;

生成的查询(来自 SQL Server Profiler)将如下所示:

SELECT 
1 AS [C1], 
[Distinct1].[CompanyId] AS [CompanyId], 
[Distinct1].[CompanyName] AS [CompanyName]
[Distinct1].[CompanyPriority] AS [CompanyPriority]
FROM ( SELECT DISTINCT 
    [Extent1].[CompanyId] AS [CompanyId], 
    [Extent1].[CompanyName] AS [CompanyName]
    [Extent1].[CompanyPriority] AS [CompanyPriority]
    FROM [dbo].[vwCompany] AS [Extent1]
) AS [Distinct1]

【讨论】:

    【解决方案4】:

    尝试在查询末尾使用 .Distinct(),例如

    (from r in ctx.MyTable where SomeCondition select r).Distinct();
    

    http://msdn.microsoft.com/en-us/library/system.linq.enumerable.distinct.aspx

    如果需要,您还可以提供 IEqualityComparer。但是,要使用 IEqualityComparer,必须首先使用 .ToEnumerable() 实现生成的可枚举。这样做意味着 Distinct() 操作是在客户端而不是数据库服务器上执行的。

    http://msdn.microsoft.com/en-us/library/bb338049.aspx

    IEqualityComparer 允许您准确控制哪些记录被视为平等,因此与其他记录没有区别。

    如果您只想选择表格的一部分列,请更改

    select r
    

    选择像这样的匿名类型:

    (from r in ctx.MyTable where SomeCondition
        select new 
        { 
            CompanyId = r.CompanyId, 
            CompanyName = r.CompanyName, 
            CompanyPriority = r.CompanyPriority
        }
    ).Distinct();
    

    或者如果你需要一个强类型对象(例如,因为你在 MVC 中使用强类型视图:

    public class CompanyModel
    {
        public int CompanyId { get; set; }
        public string CompanyName { get; set; }
        public int CompanyPriority { get; set; }
    }
    
    // Then in the Linq statement
    
    (from r in ctx.MyTable where SomeCondition
        select new CompanyModel()
        {
            CompanyId = r.CompanyId, 
            CompanyName = r.CompanyName, 
            CompanyPriority = r.CompanyPriority
        }
    ).Distinct();
    

    【讨论】:

      【解决方案5】:

      试试:

      var results = (from company in context.Companies
          select new {
              CompanyId = company.CompanyId,
              CompanyName = company.CompanyName,
              CompanyPriority = company.CompanyPriority
          }).Distinct();
      

      关键是获取可以唯一的查询片段,然后调用.Distinct() 扩展。如果您将 configID 属性保留在其中,它们都将是唯一的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-29
        • 2011-06-29
        • 1970-01-01
        • 1970-01-01
        • 2010-10-07
        • 2015-08-20
        • 2011-04-28
        相关资源
        最近更新 更多