显然,您正在尝试使客户组的姓氏具有相同的值。一些数据库管理系统不支持 GroupBy,尽管这种情况很少见,因为 Grouping 是一种非常常见的数据库操作。
要查看您的数据库管理系统是否支持分组,请尝试使用 GroupBy 方法语法。以ToList结尾,执行GroupBy:
var customerGroupsWithSameLastName = dbContext.Customers.GroupBy(
// Parameter KeySelector: make groups of Customers with same value for LastName:
customer => customer.LastName)
.ToList();
如果这可行,那么与您的 DbContext 通信的 DBMS 将接受 GroupBy。
结果是组列表。每个 Group 对象都实现了IGrouping<string, Customer>,这意味着每个 Group 都有一个 Key:该组中所有客户的公共 LastName。该组是(没有)具有此姓氏的所有客户的序列。
顺便说一句:GroupBy 的一个更有用的重载有一个额外的参数:resultSelector。使用 resultSelector 您可以影响输出:它不是IGrouping 对象的序列,而是您使用函数指定的对象序列。
这个函数有两个输入参数:共同的姓氏和所有具有这个姓氏值的客户。此函数的返回值是您的输出序列的元素之一:
var result = dbContext.Customers.GroupBy(
customer => customer.LastName,
// parameter resultSelector: take the lastName and all Customers with this LastName
// to make one new:
(lastName, customersWithThisLastName) => new
{
LastName = lastName,
Count = customersWithThisLastName.Count(),
FirstNames = customersWithThisLastName.Select(customer => customer.FirstName)
.ToList(),
... // etc
})
.ToList();
回到你的问题
如果上面的代码显示您的 DBMS 不支持该功能,您可以让您的本地进程进行分组:
var result = dbContext.Customer
// if possible: limit the number of customers that you fetch
.Where(customer => ...)
// if possible: limit the customer properties that you fetch
.Select(customer => new {...})
// Transfer the remaining data to your local process:
.AsEnumerable()
// Now your local process can do the GroupBy:
.GroupBy(customer => customer.LastName)
.ToList();
由于您选择了完整的客户,所有客户数据无论如何都会被传输,因此如果您让本地进程执行 GroupBy 并不会造成太大损失,除了 DBMS 可能更优化以更快地进行分组您的本地进程。
警告:数据库管理系统在选择数据方面进行了极大优化。数据库查询中较慢的部分之一是将所选数据从 DBMS 传输到本地进程。因此,如果您必须使用AsEnumerable(),您应该意识到您将传输到现在为止选择的所有数据。确保在AsEnumerable() 之后不转移任何你不会使用的东西;所以如果你只对FirstName和LastName感兴趣,不要传输主键、外键、地址等。让你的DBMS做Where and Select`