LINQ to Entities看似奇怪的行为

时间:2018-02-02 08:20:38

标签: linq group-by linq-to-entities

我有这个Linq查询,非常奇怪地转换为SQL。我得到了正确的结果但必须有更好的方法。问题1是:

  1. 为什么在SQL中我没有得到任何组,没有计数和所有 返回的列而不是2;那么C#的结果是否正确? (我查看过探查器)。
  2. 和问题2是:

    1. 我想略微修改查询,以便我也得到 计数为0的结果。目前我只得到计数的地方> 0 因为小组来。
    2. LINQ:

      async

      请注意,如果我在中间删除了.ToList(),我会得到异常" linq中只支持无参数构造函数和初始化函数"。

      感谢您的输入

1 个答案:

答案 0 :(得分:1)

你遇到了几个问题。我认为原因是您不知道AsEnumerable的查询与AsQueryable的查询之间存在差异。

AsEnumerable查询包含枚举查询中元素的所有信息。查询将由您的流程执行。

AsQueryable查询,包含ExpressionProvider。提供者知道谁将执行查询,以及如何与此执行者通信。执行者往往是一个数据库,但它可以是其他东西,如互联网查询,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,
    });

我选择不将结果放在元组中,因为如果混淆字段,你将失去编译器的帮助。但如果你真的想适合自己。