2014-09-11 67 views
0

我有一个查询,它是这样定义的,我用它来生成一个JSON输出。重点是,我已经应用了Distinct方法,但它仍然显示重复的项目。例如,我有许多项目的值为“未分类”,而我只需要其中的一个,其他值也一样。这是我的查询:如何从C#中的LINQ查询获取不同的项目?

var results = db.Users.OfType<Business>() 
       .Where(b => b.StateID == state && (term == null || b.Description.ToLower().Contains(term.ToLower()))) 
       .Distinct().Select(x => new { id = x.StateID, value = x.Description }).Take(5).ToList(); 

任何想法,如何解决它?我想我需要以某种方式特别应用不同的值。

+0

什么字段是“未分类”?如果两个记录在该字段中具有相同的值,那么您选择哪个? – 2014-09-11 13:24:06

回答

4

我怀疑你需要切换你的DistinctSelect调用。 Distinct将比较您可能期望给出您的投影的更多字段,这可能意味着比较实际比较的字段以外的字段。首先调用Select将减少比较的字段的数量以生成不同的列表。

var results = db.Users.OfType<Business>() 
      .Where(b => b.StateID == state && (term == null || b.Description.ToLower().Contains(term.ToLower()))) 
      .Select(x => new { id = x.StateID, value = x.Description }) 
      .Distinct() 
      .Take(5) 
      .ToList(); 
+0

不知道为什么downvote,看起来像我合理的答案 – DavidG 2014-09-11 13:21:16

+1

“不同将比较你的类中的所有字段”只适用于已覆盖'Equals'来比较所有字段的匿名类型和类型。我没有倒下,但想明确表达这一点。 – 2014-09-11 13:22:53

+0

+1为原创性,但同意@DStanley,它更好地编辑答案,以避免误解 – 2014-09-11 13:25:14

0

Business类需要重写object.Equalsobject.GetHashCode方法和Distinct方法之前实施IEquatable<T>将正常工作。

参见MSDN例子:Enumerable.Distinct Method (IEnumerable)

+1

这只是一种方式 - 你也可以实现一个'IEqualityComparer ',这可能是一个更好的选择,因为Overrriding Equals将应用于所有场景而不仅仅是这一场景。 – 2014-09-11 13:25:41

+0

这是Microsoft推荐的实际提供默认'IEqualityComparer'的方法。如果你需要运行一个不同的'Distinct()'从默认的'''IEqualityComparer'将会很好。链接中的注释就在这里。 :) – toadflakz 2014-09-12 07:38:14

+0

是的,但问题中的要求可能不一定需要是该类型的“默认”。这可能只是针对这种情况,在这种情况下,_non-default_'IEqualityComparer'会更合适。 – 2014-09-12 12:50:01

0

Distinct()返回序列中的不同元件通过使用默认的相等比较器来比较值。所以你应该创建BusinessEqualityComparer类应该实现IEqualityComparer接口

class BusinessEqualityComparer : IEqualityComparer<Business> 
{ 

    public bool Equals(Business b1, Business b2) 
    { 
     if (b1.ID == b2.ID) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 


    public int GetHashCode(Business business) 
    { 
     int hCode = business.ID^business.ID^business.ID; 
     return hCode.GetHashCode(); 
    } 
1

.NET没有办法知道要如何确定你的对象“平等”的方式。默认情况下,引用类型的相等性仅基于引用相等性,因此默认情况下,所有对象都是不同的。您可以提供custom equality comparerDistinct()。例如,如果你只是在一个.Name属性比较以确定唯一性,它可能是这个样子:

class BusinessComparer : IEqualityComparer<Business> 
{ 
    public bool Equals(Business x, Business y) 
    { 
     if (Object.ReferenceEquals(x, y)) 
      return true; 
     if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) 
      return false; 
     return x.Name == y.Name; 
    } 

    public int GetHashCode(Business business) 
    { 
     if (Object.ReferenceEquals(business, null)) 
      return 0; 
     int hashBusinessName = business.Name == null ? 0 : business.Name.GetHashCode(); 
     return hashProductName; 
    } 
} 

如果这种平等是核心业务逻辑,而不是仅仅在这个特殊的比较中,那么你可能连在Business本身上实施EqualsGetHashCode,以便可以在其他地方使用相等比较。请注意,这可能是已经假定参照平等的现有代码的重大改变。

0

.Distinct()如果不提供手动比较器,将使用处理类型的默认比较器,最终将使用Business类的.Equals().GetHashCode()

所以,除非你已经重写了这些方法,否则.Distinct()将只删除参考明确的重复项。

相关问题