Sto provando a portare un elenco di oggetti che hanno un elenco di oggetti figlio anche dal database.
Ecco un esempio
public class User
{
public int Id { get; set; }
public ICollection<Child> Childs { get; set; }
}
public class Child
{
public int Id { get; set; }
public string UserId { get; set; }
public User User { get; set; }
}
Il problema qui è che non riesco a trovare un modo per portare un elenco di utenti e filtrare contemporaneamente Childs con una condizione.
Ho provato qualcosa del genere:
users = _context.Users.Where(e => e.Childs.Any(ec => ec.Id > 1))
Ma usando questo esempio se la condizione non è soddisfatta non riporterà l'Utente e voglio tutti gli utenti anche se non hanno Childs o la condizione non è soddisfatta.
Ho anche trovato questo progetto: https://github.com/zzzprojects/EntityFramework-Plus ma sembra che non supporti EF Core per quello che voglio fare.
Qualcuno ha qualche suggerimento?
Disclaimer : sono il proprietario del progetto Entity Framework Plus
La nostra libreria non supporta ancora il filtro delle query per .NET Core a causa del problema delle query N + 1.
Sotto la nostra cappa per EF6, la nostra biblioteca stava solo facendo una semplice proiezione.
Qualcosa di simile a questo usando le tue informazioni:
var users = _Context.Users.Select(x => new {
Users = x,
Childs = x.Childs.Any(ec => ec.Id > 1)
})
.ToList()
.Select(x => x.Users)
.ToList();
Tuttavia, per EF Core, la stessa proiezione rende un database andata e ritorno per ottenere un figlio per ogni utente (query N + 1)
Puoi provare la seguente proiezione e vedere se ottieni lo stesso errore.
Credo che fino a quando il team EF Core non lo risolverà, per quanto ne sappia, non c'è modo di filtrare le entità figlio.
SELECT [x].[Id], [x].[ColumnInt]
FROM [Lefts] AS [x]
go
exec sp_executesql N'SELECT CASE
WHEN EXISTS (
SELECT 1
FROM [Rights] AS [ec1]
WHERE ([ec1].[Id] > 1) AND (@_outer_Id1 = [ec1].[LeftId]))
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END',N'@_outer_Id1 int',@_outer_Id1=1
go
exec sp_reset_connection
go
exec sp_executesql N'SELECT CASE
WHEN EXISTS (
SELECT 1
FROM [Rights] AS [ec1]
WHERE ([ec1].[Id] > 1) AND (@_outer_Id1 = [ec1].[LeftId]))
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END',N'@_outer_Id1 int',@_outer_Id1=2
go
exec sp_reset_connection
go
exec sp_executesql N'SELECT CASE
WHEN EXISTS (
SELECT 1
FROM [Rights] AS [ec1]
WHERE ([ec1].[Id] > 1) AND (@_outer_Id1 = [ec1].[LeftId]))
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END',N'@_outer_Id1 int',@_outer_Id1=3
go
exec sp_reset_connection
go
exec sp_executesql N'SELECT CASE
WHEN EXISTS (
SELECT 1
FROM [Rights] AS [ec1]
WHERE ([ec1].[Id] > 1) AND (@_outer_Id1 = [ec1].[LeftId]))
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END',N'@_outer_Id1 int',@_outer_Id1=4
go
exec sp_reset_connection
go
exec sp_executesql N'SELECT CASE
WHEN EXISTS (
SELECT 1
FROM [Rights] AS [ec1]
WHERE ([ec1].[Id] > 1) AND (@_outer_Id1 = [ec1].[LeftId]))
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END',N'@_outer_Id1 int',@_outer_Id1=5
go
Sotto-domanda RISPOSTA:
Con la nuova versione di .NET core 2.0 questo problema è stato risolto?
Sfortunatamente, Entity Framework non è ancora in grado di gestire il cast correttamente con V2.x.
Ad esempio, questo LINQ che utilizza il metodo Cast non funziona:
var ids = ctx.MyTables
.Cast<IMyTable>()
.Cast<MyTable>()
.Where(x => x.SomeKey.Equals(keyId))
.Select(x => x.MyFieldIntegerIWant)
.ToList();
EDIT: aggiornamento di stato n. 1
Sfortunatamente, il team EF Core non ha ancora risolto il problema delle query N + 1 con la proiezione.
Guardando l'ultimo stato della v3.0, non credo che pianifichino presto di risolvere questo tipo di problema: https://github.com/aspnet/EntityFrameworkCore/issues/10001#issuecomment-456581915
EDIT: aggiornamento dello stato n. 2
La funzione IncludeFilter
è ora supportata nell'ultima versione di EF Plus (EF Core 2.xe EFCore 3.x)