Question

J'ai une entité que je voudrais comparer à un sous-ensemble et déterminer pour sélectionner tous, sauf le sous-ensemble.

Alors, ma requête ressemble à ceci:

Products.Except(ProductsToRemove(), new ProductComparer())

La méthode ProductsToRemove() retourne un List<Product> après qu'il effectue quelques tâches. Ainsi, dans sa forme la plus simple, il est ci-dessus.

La classe ProductComparer() ressemble à ceci:

public class ProductComparer : IEqualityComparer<Product>
{
    public bool Equals(Product a, Product b)
    {
        if (ReferenceEquals(a, b)) return true;

        if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
            return false;

        return a.Id == b.Id;
    }

    public int GetHashCode(Product product)
    {
        if (ReferenceEquals(product, null)) return 0;
        var hashProductId = product.Id.GetHashCode();
        return hashProductId;
    }
}

Cependant, je reçois sans cesse l'exception suivante:

  

LINQ to Entities ne reconnaît pas   la méthode   « System.Linq.IQueryable1[UnitedOne.Data.Sql.Product] Except[Product](System.Linq.IQueryable1 [UnitedOne.Data.Sql.Product],   System.Collections.Generic.IEnumerable1[UnitedOne.Data.Sql.Product], System.Collections.Generic.IEqualityComparer1 [UnitedOne.Data.Sql.Product]) »   méthode, et cette méthode ne peut pas être   traduit en une expression de magasin.

Était-ce utile?

La solution

LINQ to Entities n'exécute pas réellement votre requête, il est interprétariat votre code, le convertir en TSQL, puis l'exécution que sur le serveur.

Sous les couvertures, il est codé avec la connaissance de la façon dont les opérateurs et les fonctions communes fonctionnent et comment les concernent TSQL. Le problème est que les développeurs de L2E ont aucune idée de la façon dont vous implémentez IEqualityComparer exactement. Par conséquent, ils ne peuvent pas comprendre que lorsque vous dites de classe A == Classe B vous dire (par exemple) « Où Person.FirstName == == Person.LastName FirstName et LastName ».

Alors, quand l'interpréteur L2E frappe une méthode qu'il ne reconnaît pas, il jette cette exception.

Il y a deux façons de contourner cela. Tout d'abord, développer un where () qui répond à vos besoins en matière d'égalité, mais qui ne repose pas sur une méthode personnalisée. En d'autres termes, le test pour l'égalité des propriétés de l'instance plutôt qu'une méthode equals définie sur la classe.

En second lieu, vous pouvez déclencher l'exécution de la requête, puis effectuez vos comparaisons en mémoire. Par exemple:

var notThisItem = new Item{Id = "HurrDurr"};
var items = Db.Items.ToArray(); // Sql query executed here
var except = items.Except(notThisItem); // performed in memory

Il est évident que cela apportera beaucoup plus de données à travers le fil et être plus gourmand en mémoire. La première option est généralement le meilleur.

Autres conseils

Vous essayez de convertir l'appel Except avec votre IEqualityComparer personnalisé dans Entity SQL.

De toute évidence, votre classe ne peut pas être convertie en SQL.

Vous devez écrire Products.AsEnumerable().Except(ProductsToRemove(), new ProductComparer()) pour le forcer à exécuter sur le client. Notez que ce téléchargera tous les produits du serveur.


Par ailleurs, votre classe ProductComparer devrait être un singleton, comme ceci:

public class ProductComparer : IEqualityComparer<Product> {
    private ProductComparer() { }
    public static ProductComparer Instance = new ProductComparer();

    ...
}

Le IEqualityComparer<T> ne peut être exécutée localement, il ne peut pas être traduit à une commande SQL, d'où l'erreur

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top