Pourquoi ne puis-je pas utiliser ToListAsync () lorsque j'utilise un paramètre pour le prédicat dans EF7?

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

Question

J'implémente actuellement le modèle de référentiel pour mon application ASP.VNext. Je voudrais que les méthodes soient asynchrones et filtrables. J'ai donc conçu la méthode d'interface suivante:

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

et voudrait l'implémenter comme ceci (avec une instance privée de DbContext ctx ):

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

Cependant, je ne peux utiliser FirstOrDefaultAsync() lors du codage en dur du prédicat comme ceci:

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

Lorsque je passe le prédicat, je n’obtiens que FirstOrDefault() sans l’option async. Pour rendre ma méthode asynchrone, je dois écrire

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;
}

J'ai deux questions à ce sujet:

  1. Pourquoi n'est-il pas possible d'accéder à la méthode FirstOrDefaultAsync() lors du passage d'un prédicat?

  2. Est-ce que ma solution à l'aide de await Task.Run(synchronousMethod) le même comportement qu'un appel à FirstOrDefaultAsync() ?

Réponse acceptée

FirstOrDefaultAsync est défini comme une méthode d'extension pour IQueryable<T> .

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

ctx.MyEntities.Where(predicate) renvoie IEnumerable<MyEntity> , car vous appelez la méthode d'extension Enumerable.Where , et non la méthode Queryable.Where one

Pour que cela fonctionne, changez le predicate de Func<MyEntity, bool> à Expression<Func<MyEntity, bool>> . Cela signifie que le predicate n'est plus simplement une fonction donnant le résultat souhaité, mais une description de cette fonction, qu'Entity Framework peut ensuite traduire en SQL.

Et non, l'utilisation de Func<MyEntity, bool> dans une tâche n'aurait pas le même comportement. Cela chargerait les lignes du serveur de base de données sans aucun filtrage et évaluerait chacune d'elles sur le client de base de données jusqu'à ce qu'une correspondance soit trouvée. Cela ajouterait beaucoup de frais généraux.




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi