我有这个Linq查询,非常奇怪地转换为SQL。我得到了正确的结果但必须有更好的方法。问题1是:
和问题2是:
LINQ:
async
请注意,如果我在中间删除了.ToList(),我会得到异常" linq中只支持无参数构造函数和初始化函数"。
感谢您的输入
答案 0 :(得分:1)
你遇到了几个问题。我认为原因是您不知道AsEnumerable
的查询与AsQueryable
的查询之间存在差异。
AsEnumerable查询包含枚举查询中元素的所有信息。查询将由您的流程执行。
AsQueryable
查询,包含Expression
和Provider
。提供者知道谁将执行查询,以及如何与此执行者通信。执行者往往是一个数据库,但它可以是其他东西,如互联网查询,jswon文件等。
在您的情况下,执行者将是一个数据库,语言将是SQL。
当调用IQueryable的GetEnumerator()函数时,将命令Provider将Expression转换为执行程序知道的语言。已翻译的查询将发送到执行程序,并将返回的数据放入枚举器(而不是IEnumerable!)
当然SQL不知道System.Tuple
是什么,也不知道像String.operator +
因此,您的提供程序无法将您的表达式转换为SQL。这就是你必须做第一个ToList()
的原因您不能使用任何自己的函数进行IQueryable查询,只能使用有限数量的.NET函数。
See this list of supported and unsupported Linq methods
不建议在查询的这个体育场中使用ToList(),因为它枚举了序列的所有元素,实际上你只需要一个枚举器。可能是在您的查询的其余部分,您只需要一些元素。在这种情况下,枚举所有这些内容以创建列表,然后再次枚举以完成剩余的LINQ将是一种浪费。
而不是ToList()使用Enumerable.AsEnumerable()。这会将查询的所有数据带到本地内存并创建它的IEnumerable:元素尚未枚举。这将允许您使用其余查询调用本地函数。
另一个问题是您将更多数据传输到本地内存而不是计划使用。数据库查询的一个较慢的部分是将数据传输到您的进程。您应该尽量减少数据量。
您获取了所有审核,并创建了(Type,CreatedBy)具有相同值的审核组。换句话说:同一组中的所有审核对于(Type,CreatedBy)具有相同的值。该值也是该组的密钥。
您不希望本地所有审核,您只需要组的密钥和该组的元素数(=具有(Type,CreatedBy)的审核数等于密钥。
这是您传输到本地内存所需的唯一数据:Type,CreatedBy和组中的审核次数:
var result = db1.Audits.GroupBy(o => new { o.Type, o.CreatedBy })
.Select(group => new
{
Type = group.Key.Type,
CreatedBy = group.Key.CreatedBy,
AuditCount = group.Count(),
})
.OrderBy(item => item.CreatedBy)
// the data that is left is the data you need locally
// bring to local memory:
.AsEnumerable()
// if you want you can put Type and CreatedBy into one string
.Select(item => new
{
AuditType = item.Type + item.CreatedBy,
AuditCount = item.AuditCount,
});
我选择不将结果放在元组中,因为如果混淆字段,你将失去编译器的帮助。但如果你真的想适合自己。