Linq to Entities选择Distinct

时间:2012-11-27 15:04:09

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

我不确定我错过了什么,但我整个下午一直在吵架。

我有一个公司的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

我正在努力获得一份独特的公司名单。我要exectute的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]

根本没有明确的运算符:(

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

编辑2:

我正试图尽可能接近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中这应该如此困难我不知道:(

5 个答案:

答案 0 :(得分:2)

尝试在查询结束时使用.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()实现生成的可枚举项。这样做意味着在客户端而不是在DB服务器上执行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();

答案 1 :(得分:1)

-EDITED: -

忽略我之前提到的所有代码(结束编辑部分之后的所有代码)。我尝试了进一步测试。插入以下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编辑 -

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

您要查找的内容需要您在帖子中提到的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]

答案 2 :(得分:0)

尝试:

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

关键是获取可以唯一的查询部分,然后调用.Distinct()扩展名。如果你将configID属性保留在那里,它们将是唯一的。

答案 3 :(得分:0)

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 :(得分:0)

难道不是两张桌子吗?一个

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

另一个

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

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