Perché non è possibile utilizzare ToListAsync () quando si utilizza un parametro per il predicato in EF7?

asp.net-core c# entity-framework-core

Domanda

Attualmente sto implementando il pattern di repository per la mia applicazione ASP.VNext. Vorrei che i metodi fossero asincroni e filtrabili. Quindi ho ideato il seguente metodo di interfaccia:

Task<TEntity> GetOneAsync(Func<TEntity,bool> predicate);

e vorrei implementarlo in questo modo (con un'istanza di DbContext privata ctx ):

public async Task<MyEntity> GetOneAsync(Func<MyEntity,bool> predicate) 
{
    // compiler error
    return await ctx.MyEntities.Where(predicate).FirstOrDefaultAsync();
}

Tuttavia, posso utilizzare solo FirstOrDefaultAsync() durante l'hardcoding del predicato come questo:

return await ctx.MyEntites.Where(e => e.Id == 1).FirstOrDefaultAsync();

Quando si passa il predicato, ottengo solo il FirstOrDefault() senza l'opzione async, quindi per rendere il mio metodo asincrono devo scrivere

public async Task<MyEntity> GetOneAsync(Func<MyEntity,bool> predicate) 
{
    //save to a local variable to prevent calling a disposed DbContext
    var entities = await Task.Run(() => ctx.Contracts.Where(predicate).FirstOrDefault());
    return entities;
}

Ho due domande a riguardo:

  1. Perché non è possibile accedere al metodo FirstOrDefaultAsync() quando si passa un predicato?

  2. La mia soluzione che utilizza await Task.Run(synchronousMethod) lo stesso comportamento di una chiamata a FirstOrDefaultAsync() ?

Risposta accettata

FirstOrDefaultAsync è definito come un metodo di estensione per IQueryable<T> .

ctx.MyEntities.Where(e => e.Id == 1) restituisce IQueryable<MyEntity> .

ctx.MyEntities.Where(predicate) restituisce IEnumerable<MyEntity> , perché si chiama Enumerable.Where metodo di estensione, non il Queryable.Where uno.

Per farlo funzionare, modifica il predicate da Func<MyEntity, bool> a Expression<Func<MyEntity, bool>> . Ciò significa che il predicate non è più solo una funzione che fornisce il risultato desiderato, ma una descrizione di tale funzione, che Entity Framework può quindi tradurre in SQL.

E no, l'uso di Func<MyEntity, bool> all'interno di un'attività non avrebbe lo stesso comportamento. Questo caricherà le righe dal server db senza alcun filtraggio e valuterà tutte e ognuna sul client db fino a quando non viene trovata una corrispondenza. Ciò aggiungerebbe un sacco di spese generali.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché