Ich habe einige Glocken in meiner Datenbank mit der gleichen Nummer. Ich möchte sie alle ohne Vervielfältigung erhalten. Ich habe eine Vergleichsklasse erstellt, um diese Arbeit zu erledigen, aber die Ausführung der Funktion verursacht eine große Verzögerung der Funktion ohne Unterschied, von 0,6 Sekunden bis 3,2 Sekunden!
Mache ich es richtig oder muss ich eine andere Methode anwenden?
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
quelle
quelle
Antworten:
Ihre
GetHashCode
Implementierung gibt immer den gleichen Wert zurück.Distinct
stützt sich auf eine gute Hash-Funktion, um effizient zu arbeiten, da intern eine Hash-Tabelle erstellt wird .Bei der Implementierung von Schnittstellen von Klassen ist es wichtig, die Dokumentation zu lesen , um zu wissen, welchen Vertrag Sie implementieren sollen. 1
In Ihrem Code besteht die Lösung darin, ihn dort weiterzuleiten und entsprechend
GetHashCode
zuClass_reglement.Numf.GetHashCode
implementieren.Abgesehen davon ist Ihre
Equals
Methode voller unnötigen Codes. Es könnte wie folgt umgeschrieben werden (gleiche Semantik, ¼ des Codes, besser lesbar):Schließlich ist der
ToList
Anruf unnötig und zeitaufwändig:AddRange
Akzeptiert alle,IEnumerable
sodass eine Konvertierung in aList
nicht erforderlich ist.AsEnumerable
ist auch hier redundant, da die Verarbeitung des Ergebnisses inAddRange
dies ohnehin verursacht.1 Das Schreiben von Code, ohne zu wissen, was er tatsächlich tut, wird als Frachtkultprogrammierung bezeichnet . Es ist eine überraschend weit verbreitete Praxis. Es funktioniert grundsätzlich nicht.
quelle
GetHashCode
. Beachten Sie jedoch, dass in der Dokumentation vonIEqualityComparer<T>
nicht angegeben ist, was mitnull
Argumenten zu tun ist. Die im Artikel enthaltenen Beispiele behandeln dies jedoch auch nichtnull
.Versuchen Sie diesen Code:
Beispiel für seine Verwendung wäre
quelle
GetHashCode
Bedarf den Ausdruck verwenden , wie gut:return _expr.Invoke(obj).GetHashCode();
Sehen Sie diesen Beitrag für eine Verwendung davon.Nur Code mit Implementierung
GetHashCode
undNULL
Validierung:Beispiel: Liste von Class_reglement, die sich durch Numf unterscheidet
quelle
Die Einbeziehung Ihrer Vergleichsklasse (oder genauer gesagt des
AsEnumerable
Aufrufs, den Sie verwenden mussten, um sie zum Laufen zu bringen) bedeutete, dass die Sortierlogik nicht mehr auf dem Datenbankserver, sondern auf dem Datenbankclient (Ihrer Anwendung) basierte. Dies bedeutete, dass Ihr Client jetzt eine größere Anzahl von Datensätzen abrufen und dann verarbeiten muss. Dies ist immer weniger effizient als die Suche in der Datenbank, in der die entsprechenden Indizes verwendet werden können.Sie sollten versuchen, stattdessen eine where-Klausel zu entwickeln, die Ihren Anforderungen entspricht. Weitere Informationen finden Sie unter Verwenden eines IEqualityComparer mit einer LINQ to Entities Except-Klausel .
quelle
Wenn Sie eine generische Lösung ohne Boxen wollen:
Verwendung:
quelle
IEquatable<T>
kann mit modernen Frameworks viel einfacher sein.Sie erhalten eine schöne einfache
bool Equals(T other)
Funktion und es gibt kein Herumspielen beim Casting oder Erstellen einer separaten Klasse.Beachten Sie, dass Sie dies implementieren müssen,
GetHashCode
wenn Sie dies in einem Wörterbuch oder mit etwas Ähnlichem verwendenDistinct
.PS. Ich glaube nicht, dass benutzerdefinierte Equals-Methoden mit dem Entity-Framework direkt auf der Datenbankseite funktionieren (ich denke, Sie wissen das, weil Sie AsEnumerable ausführen), aber dies ist eine viel einfachere Methode, um einfache Equals für den allgemeinen Fall zu erstellen.
Wenn die Dinge nicht zu funktionieren scheinen (z. B. doppelte Schlüsselfehler beim Ausführen von ToDictionary), setzen Sie einen Haltepunkt in Equals, um sicherzustellen, dass er getroffen wird, und stellen Sie sicher, dass Sie ihn
GetHashCode
definiert haben (mit Schlüsselwort zum Überschreiben).quelle
.Equals()
Methode scheinen Sie mitother.Hometown
sich selbst verglichen zu haben, anstattthis.Hometown