J'ai quelques cloches dans ma base de données avec le même numéro. Je veux tous les obtenir sans duplication. J'ai créé une classe de comparaison pour faire ce travail, mais l'exécution de la fonction provoque un gros retard de la fonction sans distinction, de 0,6 sec à 3,2 sec!
Est-ce que je fais les choses correctement ou dois-je utiliser une autre méthode?
reg.AddRange(
(from a in this.dataContext.reglements
join b in this.dataContext.Clients on a.Id_client equals b.Id
where a.date_v <= datefin && a.date_v >= datedeb
where a.Id_client == b.Id
orderby a.date_v descending
select new Class_reglement
{
nom = b.Nom,
code = b.code,
Numf = a.Numf,
})
.AsEnumerable()
.Distinct(new Compare())
.ToList());
class Compare : IEqualityComparer<Class_reglement>
{
public bool Equals(Class_reglement x, Class_reglement y)
{
if (x.Numf == y.Numf)
{
return true;
}
else { return false; }
}
public int GetHashCode(Class_reglement codeh)
{
return 0;
}
}
c#
linq
iequalitycomparer
Akrem
la source
la source
Réponses:
Votre
GetHashCode
implémentation renvoie toujours la même valeur.Distinct
repose sur une bonne fonction de hachage pour fonctionner efficacement car elle crée en interne une table de hachage .Lors de l'implémentation d'interfaces de classes, il est important de lire la documentation , pour savoir quel contrat vous êtes censé implémenter. 1
Dans votre code, la solution est de transmettre
GetHashCode
àClass_reglement.Numf.GetHashCode
et mettre en œuvre de manière appropriée là.En dehors de cela, votre
Equals
méthode est pleine de code inutile. Il pourrait être réécrit comme suit (même sémantique, ¼ du code, plus lisible):Enfin, l'
ToList
appel est inutile et prend du temps:AddRange
accepte tout,IEnumerable
donc la conversion en unList
n'est pas nécessaire.AsEnumerable
est également redondant ici car le traitement du résultat enAddRange
provoquera de toute façon cela.1 Écrire du code sans savoir ce qu'il fait réellement s'appelle la programmation culte du fret . C'est une pratique étonnamment répandue. Cela ne fonctionne fondamentalement pas.
la source
GetHashCode
. Cependant, notez que la documentation deIEqualityComparer<T>
ne spécifie pas quoi faire avec lesnull
arguments - mais les exemples fournis dans l'article ne gèrent pas nonnull
plus.Essayez ce code:
Un exemple de son utilisation serait
la source
GetHashCode
doit également utiliser l'expression:return _expr.Invoke(obj).GetHashCode();
voir cet article pour une utilisation de celui-ci.Juste du code, avec implémentation
GetHashCode
etNULL
validation:Exemple: liste de Class_reglement distincte par Numf
la source
L'inclusion de votre classe de comparaison (ou plus précisément de l'
AsEnumerable
appel que vous deviez utiliser pour la faire fonctionner) signifiait que la logique de tri est passée du statut basé sur le serveur de base de données à celui du client de base de données (votre application). Cela signifie que votre client doit maintenant récupérer puis traiter un plus grand nombre d'enregistrements, ce qui sera toujours moins efficace que d'effectuer la recherche sur la base de données où les index appropriés peuvent être utilisés.Vous devriez plutôt essayer de développer une clause where qui répond à vos exigences, consultez Utilisation d'un IEqualityComparer avec une clause LINQ to Entities Except pour plus de détails.
la source
Si vous voulez une solution générique sans boxe:
usage:
la source
IEquatable<T>
peut être un moyen beaucoup plus simple de le faire avec des frameworks modernes.Vous obtenez une
bool Equals(T other)
fonction simple et agréable et il n'y a pas de problème avec le casting ou la création d'une classe séparée.Notez que vous devez implémenter
GetHashCode
si vous utilisez ceci dans un dictionnaire ou avec quelque chose commeDistinct
.PS. Je ne pense pas que les méthodes Equals personnalisées fonctionnent avec le framework d'entité directement du côté de la base de données (je pense que vous le savez parce que vous faites AsEnumerable) mais c'est une méthode beaucoup plus simple pour faire un simple Equals pour le cas général.
Si les choses ne semblent pas fonctionner (comme des erreurs de clé en double lors de ToDictionary), placez un point d'arrêt dans Equals pour vous assurer qu'il est atteint et assurez-vous que vous avez
GetHashCode
défini (avec le mot-clé override).la source
.Equals()
méthode que vous semblez avoir comparéother.Hometown
à lui-même, au lieu dethis.Hometown