Ho scritto una funzione in cui verificare se il prodotto ha qualche funzionalità e trovare un prodotto con il prezzo massimo.
I miei modelli semplicemente assomigliano a questo:
public class Product
{
public long ProductID { get; set; }
[MaxLength(150)]
public string Name { get; set; }
public List<Functionality> Functionalities { get; set; }
public List<Price> Prices { get; set; }
}
public class Functionality
{
public long FunctionalityID { get; set; }
[MaxLength(150)]
public string Name { get; set; }
[Required]
public long ProductID { get; set; }
public Product Product { get; set; }
}
public class Price
{
public long PriceID { get; set; }
public decimal Value { get; set; }
[Required]
public long ProductID { get; set; }
public Product Product { get; set; }
}
quindi la mia funzione di sincronizzazione per trovare il prodotto corretto assomiglia a questo:
public List<Product> GetList(ProductFiltersDto filters)
{
return _context.Product
.Include(x => x.Functionality)
.Include(x => x.Price)
.Where(x =>
CheckCollectionFilter(x.Functionality.Select(f => f.FunctionalityID), filters.Functionalities) &&
CheckMaximumPrice(x.Prices , filters.MaxPrice)
)
.ToList();
}
sotto la mia funzione where:
private bool CheckCollectionFilter<T>(IEnumerable<T> collection, List<T> filterCollection)
{
if (filterCollection != null)
{
var result = true;
foreach (var filterValue in filterCollection)
{
if (!collection.Contains(filterValue))
{
result = false;
break;
}
}
return result;
}
else
{
return true;
}
}
private bool CheckMaximumPrice(List<Price> prices, decimal? avalibleMinPrice)
{
return avalibleMinPrice.HasValue && prices.Count > 0 ? prices.Min(x => x.Value) <= avalibleMinPrice : true;
}
Per il codice sopra tutto funziona bene. Ma quando cambio ToList()
a ToListAsync()
ho un errore
Espressione di tipo 'System.Collections.Generic.IAsyncEnumerable
1[System.Int64]' cannot be used for parameter of type 'System.Collections.Generic.IEnumerable
1 [System.Int64]' di metodo 'Boolean CheckCollectionFilter [Int64] (Sistema .Collections.Generic.IEnumerable1[System.Int64], System.Collections.Generic.List
1 [System.Int64]) 'Nome parametro: arg0
Provo poche cose per cambiare IEnumerable
in IAsyncEnumerable
e modificare la mia funzione per lavorare con la versione di asyn ma stil i ottiene errore (non trovo un modo per cambiare List<long>
in IAsyncEnumerable<long>
in where clausola).
Ho letto che le funzioni di EF Core Async hanno alcune limitazioni ma forse qualcuno sa che questo può essere raggiunto o per ora dovrei lasciare questo e rimanere con la soluzione di sincronizzazione?
Non appena si passa da IQueriable<T>
a IEnumerable<T>
, EntityFramework eseguirà la query fino a quel momento sul server di database estraendo tutti i dati in memoria e eseguirà il resto della query in memoria.
Se si desidera mantenerlo in esecuzione nel server database, è necessario mantenere la query su IQueriable<T>
e utilizzare alberi di espressioni anziché codice eseguibile.
Dovrai inventare qualcosa del genere:
private Expression<Func<T, bool>> CheckCollectionFilter<T>(IEnumerable<T> filterCollection);
private Expression<Func<T, bool>> CheckMaximumPrice<T>(decimal? avalibleMinPrice);
e cambia la tua richiesta a:
_context.Product
.Include(x => x.Functionality)
.Include(x => x.Price)
.Where(CheckCollectionFilter(filters.Functionalities))
.Where(CheckMaximumPrice(filters.MaxPrice))