我试图在northwind中运行GroupBy()
命令--这是我的代码
using(var ctx = new TempContext())
{
var customer = (from s in ctx.Customers
group s by s.LastName into custByLN
select custByLN);
foreach(var val in customer)
{
Console.WriteLine(val.Key);
{
foreach(var element in val)
{
Console.WriteLine(element.LastName);
}
}
}
}
它给了System.InvalidOperationException: 'Client side GroupBy is not supported'
发布于 2020-08-26 06:44:49
显然,您正在尝试使一群客户具有与LastName相同的价值。一些数据库管理系统不支持GroupBy,尽管这是非常罕见的,因为分组是非常常见的数据库操作。
若要查看数据库管理系统是否支持分组,请使用方法语法尝试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。
结果是一个组的列表。每个组对象都实现IGrouping<string, Customer>
,这意味着每个组都有一个键:这个组中所有客户的公共LastName。这个组是(没有)拥有这个LastName的所有客户的序列。
顺便说一句:一个更有用的GroupBy重载有一个额外的参数: resultSelector。使用resultSelector,您可以影响输出:它不是IGrouping
对象的序列,而是用函数指定的对象序列。
该函数有两个输入参数:公共LastName和所有具有此LastName值的客户。此函数的返回值是输出序列的元素之一:
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传输到本地进程。因此,如果您必须使用AsEnumerable()
,您应该意识到您将传输到现在为止所选择的所有数据。确保您不会在AsEnumerable()
之后传输任何不使用的内容;因此,如果您只对FirstName
和LastName
感兴趣,则不要传输主键、外键、地址等。让DBMS执行Where and
选择
https://stackoverflow.com/questions/63591066
复制相似问题