EntityFramework核心组通过给我一个订单

问题描述 投票:4回答:2

这是我的linq to sql查询:

var data = 
    from p in dbcontext.person
    group p by p.city.ToLower() into g
    select new StatsViewModel { city = g.Key, citizen_count = g.Count() };

这是我在sql server中获得的真正的sql查询:

SELECT [p0].[id_person], [p0]....
      FROM [person] AS [p0]
      ORDER BY LOWER([p0].[city])

这是一个订单,而不是一个小组...

entity-framework-core
2个回答
1
投票

使用debug(Microsoft.Extensions.Logging)我可以确认linq的.Net Core EF 2.0.1组没有转换为SQL。提出警告:

LINQ表达式'GroupBy([p] .City.ToLower(),[p])'无法翻译,将在本地进行评估。

dbug: Microsoft.EntityFrameworkCore.Query[10104]
      => Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor
      Optimized query model: 
      'from IGrouping<string, Person> g in 
          (from Person p in DbSet<Person>
          select [p]).GroupBy([p].City.ToLower(), [p])
      select new <>f__AnonymousType0<string, int>(
          [g].Key, 

              (from Person <generated>_1 in [g]
              select [<generated>_1]).Count()
      )'

提出警告:

warn: Microsoft.EntityFrameworkCore.Query[20500]
      => Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor
      The LINQ expression 'GroupBy([p].City.ToLower(), [p])' could not
      be translated and will be evaluated locally.

结果由本地组成:

dbug: Microsoft.EntityFrameworkCore.Query[10107]
      => Microsoft.EntityFrameworkCore.Query.RelationalQueryModelVisitor
      (QueryContext queryContext) => IEnumerable<<>f__AnonymousType0<string, int>> _InterceptExceptions(
          source: IEnumerable<<>f__AnonymousType0<string, int>> _Select(
              source: IEnumerable<IGrouping<string, Person>> _GroupBy(
                  source: IEnumerable<Person> _ShapedQuery(
                      queryContext: queryContext, 
                      shaperCommandContext: SelectExpression: 
                          SELECT "p0"."ID", "p0"."City", "p0"."Name"
                          FROM "People" AS "p0"
                          ORDER BY lower("p0"."City"), 
                      shaper: UnbufferedEntityShaper<Person>), 
                  keySelector: (Person p) => string p.City.ToLower(), 
                  elementSelector: (Person p) => p), 
              selector: (IGrouping<string, Person> g) => new <>f__AnonymousType0<string, int>(
                  g.Key, 
                  int Count(g)
              )), 
          contextType: ConsoleApplication3.MyContext, 
          logger: DiagnosticsLogger<Query>, 
          queryContext: queryContext)

This is the code to reproduce it:

我在这里发布源代码,以帮助那些想知道如何跟踪它的人:

模型和dbcontext

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;

namespace ConsoleApplication3
{
    public class Person
    {

        public int ID { get; set; }
        public string Name{ get; set; }
        public string City { get; set; }

    }

    public class MyContext : DbContext
    {

        public static readonly LoggerFactory MyLoggerFactory
            = new LoggerFactory(new[] {new ConsoleLoggerProvider((_, __) => true, true)});

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlite("Data Source=beer.db"); //Available here
            optionsBuilder.UseLoggerFactory(MyLoggerFactory);
            base.OnConfiguring(optionsBuilder);
        }

        public DbSet<Person> People { get; set; }
    }

}

插入数据并进行查询

        var ctx =new  MyContext();

        var p1=new Person();
        p1.City = "L'Escala";
        p1.Name = "Dani";
        ctx.People.Add(p1);

        var p2=new Person();
        p2.City = "L'Escala";
        p2.Name = "Dolors";
        ctx.People.Add(p2);

        var p3=new Person();
        p3.City = "Albons";
        p3.Name = "Joan";
        ctx.People.Add(p3);

        ctx.SaveChanges();

        var data1 = 
            from p in ctx.People
            group p by p.City.ToLower() into g
            select new { city = g.Key, citizen_count = g.Count() };

        data1.ToList();

        foreach (var v in data1)
        {
            Console.WriteLine($"{v.city} - {v.citizen_count}");
        }        

Results:

结果还可以:

albons - 1
l'escala - 2

Solution:

它看起来group by will be supported on next 2.1,评估你是否可以忍受这次性能问题。


6
投票

这是当前EF Core的GroupBy翻译的一个已知问题,由Relational: Support translating GroupBy() to SQL #2341跟踪并致力于在下一个EF Core 2.1版本中修复(根据EF Core Roadmap)。所以在那之前,你无能为力。

但是不要被生成的SQL所迷惑。 EF Core使用所谓的Cliend and Server Evaluation的组合,在这种特殊情况下意味着在检索到您看到的SQL查询的结果后,GroupBy将在内存中执行,因此实际结果将是正确的。 “唯一”问题可能是表现。

© www.soinside.com 2019 - 2024. All rights reserved.