这是我的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])
这是一个订单,而不是一个小组...
答案 0 :(得分: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
将在内存中执行,因此实际结果将是正确的。 "只有"问题可能是表现。
答案 1 :(得分: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)
我在这里发布源代码,以帮助那些想知道如何跟踪它的人:
模型和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}");
}
结果还可以:
albons - 1
l'escala - 2
看起来group by will be supported on next 2.1,评估一下这次是否能解决这个性能问题。