Ecco la mia query da linq a 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() };
E qui è la query sql reale che ottengo in SQL Server:
SELECT [p0].[id_person], [p0]....
FROM [person] AS [p0]
ORDER BY LOWER([p0].[city])
Questo è un ordine di, non un gruppo di ...
Usando debug ( Microsoft.Extensions.Logging
) posso confermare che il tuo gruppo .Net Core EF 2.0.1 di linq non è tradotto in SQL. Viene generato un avviso:
L'espressione LINQ 'GroupBy ([p] .City.ToLower (), [p])' non può essere tradotta e verrà valutata localmente.
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()
)'
Viene generato un avviso:
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.
I risultati sono composti localmente:
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)
Inserisco qui il codice sorgente per aiutare le persone che vogliono sapere come rintracciarlo:
Modello e 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; }
}
}
Inserimento di dati e creazione della query
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}");
}
I risultati sono ok:
albons - 1
l'escala - 2
Apparirà group by sarà supportato al prossimo 2.1 , valutare se è possibile vivere con questo problema di prestazioni questa volta.
Questo è un problema noto con la traduzione di GroupBy
dell'attuale core EF, tracciato da Relational: Support che traduce GroupBy () in SQL # 2341 e impegnato per essere corretto nella prossima versione di EF Core 2.1 (in base alla tabella di marcia EF Key ). Quindi fino ad allora, non c'è nulla che tu possa fare.
Ma non lasciarti ingannare dall'SQL generato. EF Core utilizza una combinazione di cosiddetti Cliend e Server Evaluation , che in questo caso specifico significa che GroupBy
verrà eseguito in memoria dopo aver recuperato il risultato della query SQL che si vede, quindi il risultato effettivo sarà corretto. Il "solo" problema potrebbe essere la prestazione.