web-dev-qa-db-fra.com

Entity Framework 3.0 Contains ne peut pas être traduit en SQL comme il l'était dans EF Core 2.2

J'essaie de migrer une API Web de .NET Core 2.2 vers .NET Core 3.0 et je suis tombé sur les éléments suivants:

public Dictionary<int, Tag> GetTagMap(IList<int> tagIds = null)
{
    var tags = context.Tag.AsNoTracking();
    if (tagIds != null)
        tags = tags.Where(t => tagIds.Contains(t.TagId));

    return tags
       .ToList()       // explicit client evaluation in 3.0
       .ToDictionary(t => t.TagId, t => t);
}

Cela générait une instruction SQL similaire à celle-ci:

SELECT TagId, Name FROM Tag WHERE TagId IN (1, 2, 3)

qui fonctionnait très bien pour une colonne correctement indexée et un petit nombre de valeurs IN.

Maintenant, je reçois l'erreur suivante suggérant que List<>.Contains la traduction n'est plus prise en charge:

System.InvalidOperationException: 'L'expression LINQ' Où (source: DbSet, prédicat: (t) => (paramètre non géré: __tagIds_0) .Contains (t.TagId)) 'n'a pas pu être traduite. Vous pouvez soit réécrire la requête dans un formulaire qui peut être traduit, soit basculer explicitement vers l'évaluation du client en insérant un appel à AsEnumerable (), AsAsyncEnumerable (), ToList () ou ToListAsync (). Voir Évaluation client vs serveur - EF Core pour plus d'informations. '

Cela suggère que les requêtes LINQ ne sont plus évaluées sur le client rupture de changement, mais AFAIK Contains n'a pas été évalué sur le client.

6
Alexei

J'ai compris ce qui se passait et pourquoi mon code ne se comportait pas comme prévu (évaluation côté serveur) et pourquoi l'évaluation explicite côté client est en fait une très bonne chose:

IList<T>.Contains a été évalué sur le client, mais List<T>.Contains est évalué côté serveur. Le simple remplacement de IList par List a permis au code de fonctionner sans évaluation explicite du client:

public Dictionary<int, Tag> GetTagMap(List<int> tagIds = null)
{
    var tags = context.Tag.AsNoTracking();
    if (tagIds != null)
        tags = tags.Where(t => tagIds.Contains(t.TagId));

    return tags
       .ToList()       // explicit client evaluation in 3.0
       .ToDictionary(t => t.TagId, t => t);
}
0
Alexei