如何在C#中从LINQ查询中获取不同的项
本文关键字:获取 查询 中从 LINQ | 更新日期: 2023-09-27 18:21:28
我有一个查询,它是这样定义的,我用它来生成JSON输出。重点是,我已经对它应用了Distinct方法,但它仍然显示重复的项。例如,我有许多值为"Unclassified"的项目,而我只想要其中一个,其他一些值也是如此。这是我的问题:
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();
知道怎么修吗?我想我需要以某种方式将Distinct具体应用于该值。
我怀疑您需要切换Distinct
和Select
调用。考虑到您的投影,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();
.NET无法知道如何确定对象中的"相等"。默认情况下,引用类型的相等仅基于引用相等,因此默认情况下所有对象都是不同的。
您可以为Distinct()
提供自定义相等比较器。例如,如果您只是在.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
本身上实现Equals
和GetHashCode
,以便在其他地方使用等式比较。请注意,这可能是对已经假定引用相等的现有代码的一个突破性更改。
Business
类需要覆盖object.Equals
和object.GetHashCode
方法并实现IEquatable<T>
,Distinct
方法才能正常工作。
请参阅MSDN示例:Enumerable.Dispinct方法(IEnumerable)
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();
}
.Distinct()
如果不提供手动比较器,将使用处理类型的默认比较器,该比较器最终将使用Business
类的.Equals()
和.GetHashCode()
。
因此,除非您重写了这些方法,否则.Distinct()
将只删除引用方式的重复项。