Linq to Sql 按类分组
本文关键字:to Sql Linq | 更新日期: 2023-09-27 18:29:32
我想将 groupedList 传递给几个函数,但是当尝试使用类而不是匿名类型进行分组时,我得到了奇怪的结果。在下面的示例中,匿名类型按预期返回 2 个结果,但具体类返回 5,就好像它甚至没有分组一样。
问题:是否可以使用具体类将Linq更改为Sql Group By?
public class person
{
public string Name;
public string State;
}
public class personGroup
{
public string State;
public personGroup(string personState)
{
State = personState;
}
}
void Main()
{
var people = new List<person>();
people.Add(new person {Name = "Bob", State = "Tx"});
people.Add(new person {Name = "Bill", State = "Tx"});
people.Add(new person {Name = "Tracy", State = "Tx"});
people.Add(new person {Name = "Steve", State = "Md"});
people.Add(new person {Name = "Kelly", State = "Md"});
var groupedPeople = people.GroupBy (p => p.State );
groupedPeople.Count().Dump();//Returns 2
var morePeople = people.GroupBy (p => new personGroup(p.State) );
morePeople.Count().Dump();//Returns 5
}
当未提供自定义IEqualityComparer
(您未提供自定义(时,GroupBy
方法使用EqualityComparer<T>.Default
来比较有问题的项目。 这将基于相关T
类型的IEquatable<T>
的实现,如果有,如果没有,那么它将仅使用该类型的object.Equals
和object.GetHashCode
。
您的自定义类型不提供任何实现,它完全依赖于 object
中定义的实现,对于引用类型,它基于对象的引用。 您创建的每个personGroup
对象都有不同的引用,因此是不同的。
匿名类型不使用默认的相等性;它们重写Equals
的定义,GetHashCode
依赖于它们所表示的每个属性的标识。
如果要使用自己的自定义类型进行分组,并且默认相等语义不是您想要的,则需要提供自定义IEqualityComparer
实现,或重写相关类型的Equals
和GetHashCode
。
在第二组中,有 5 组,因为键总是不同的。 personGroups
按引用进行比较,并且所有对象都有不同的引用。您需要重写 personGroup
类中的 Equals
和 GetHashCode
方法,以根据 State 比较实例,或者实现IEqualityComparer<personGroup>
并将其传递给 GroupBy
。
正如 Servy 上面所说,您需要创建一个类型为 PersonGroup 的自定义 IEqualityComparer 才能使您的示例正常工作。
我自己也遇到过很多,所以我创建了一个通用的 EqualityComparer,它可以与任何模型(使用属性(一起使用!
/// <summary>
/// Given two models, return TRUE if all the properties are equal,
/// else return FALSE
/// </summary>
/// <typeparam name="TModel">Type of the models being compared</typeparam>
public class PropertyEqualityComparer<TModel> : IEqualityComparer<TModel>
{
public bool Equals(TModel x, TModel y)
{
PropertyInfo[] props = typeof(TModel).GetProperties();
foreach (PropertyInfo prop in props)
{
if (!Object.Equals(prop.GetValue(x), prop.GetValue(y)))
{
return false;
}
}
return true;
}
public int GetHashCode(TModel obj)
{
int hash = 1;
PropertyInfo[] props = typeof(TModel).GetProperties();
foreach (PropertyInfo prop in props)
{
hash ^= prop.GetValue(obj).GetHashCode();
}
return hash;
}
}
有了这个类,你将能够做你做什么。
// NOTE: Use properties instead of public variables
public class Person
{
public string Name { get; set; }
public string State { get; set; }
}
// NOTE: Use properties instead of public variables
public class personGroup
{
public string State { get; set; }
}
void Main()
{
var people = new List<Person>();
people.Add(new Person{Name = "Bob", State = "Tx"});
people.Add(new Person{Name = "Bill", State = "Tx"});
var morePeople = people.GroupBy(p => new PersonGroup{State = p.State}, new PropertyEqualityComparer<PersonGroup>());
morePeople.Count();
}