Ihre Equals- und GetHashCode-Methoden nehmen vollständig verschiedene Ansätze. Insbesondere können gleiche Objekte durchaus unterschiedliche Hash-Codes haben, wenn man annimmt Action.ToString
andere Felder als TimeOfAction verwendet. Sie müssen aufeinander abgestimmt sein, sonst haben Sie keine Chance, vernünftige Ergebnisse zu erzielen. Es ist in Ordnung, wenn ungleiche Objekte denselben Hashcode haben (obwohl das die Leistung beeinträchtigt), aber gleiche Objekte muss ergeben denselben Hash-Code.
Beachten Sie, dass die Verwendung eines benutzerdefinierten Komparators dazu führt, dass der Distinct-Teil prozessintern und nicht in der Datenbank durchgeführt wird. Das mag kein Problem sein, Sie müssen es nur verstehen. EDIT: Ich hatte nicht bemerkt, dass es eine Überladung von Queryable.Distinct
die tut einnehmen IEqualityComparer<T>
. Meine Vermutung ist, dass das ist, so dass Sie benutzerdefinierte String-Vergleicher und ein paar andere bekannte Vergleicher bereitstellen können ... nicht nur willkürlichen Code. Wenn es funktioniert, wird es sowieso lokal gemacht werden. Ich wäre nicht überrascht, wenn es einfach explodieren würde.
EDIT: Wie Marc sagt, können Sie Select(x => x.TimeOfAction).Distinct().Count()
um dies in der Datenbank zu tun. Sie müssen den Aufruf von AsEnumerable
aber auch. Meine Vermutung ist, dass das so ist, weil etwas anderes nicht funktioniert hat. Sie könnten dies versuchen:
DBEntities db = new DBEntities();
IQueryable<DateTime> query =
from action in db.Action
where action.TimeOfAction > new DateTime(2010, 11, 1, 0, 0, 0)
where action.TimeOfAction < new DateTime(2011, 2, 7, 0, 0, 0)
where action.EntityName == "seant"
select action.TimeOfAction;
var count = query.Distinct().Count();
Natürlich, wenn Sie brauchen query
für etwas anderes müssten Sie auch die Originalversion behalten:
DBEntities db = new DBEntities();
IQueryable<Action> query =
from action in db.Action
where action.TimeOfAction > new DateTime(2010, 11, 1, 0, 0, 0)
where action.TimeOfAction < new DateTime(2011, 2, 7, 0, 0, 0)
where action.EntityName == "seant"
select action;
var count = query.Select(x => x.TimeOfAction).Distinct().Count();
// Use query here as well to get at full action details
Beachten Sie, dass die erneute Verwendung von query eine zweite Datenbankabfrage erzeugt. Sie müssen sich ansehen, was in Bezug auf Transaktionen vor sich geht, wenn die Zählung mit der zweiten Abfrage übereinstimmen soll... oder alle Details aus der Datenbank abrufen (mit einer ToList
aufrufen) und dann den Teil "Unterscheiden" prozessbegleitend durchführen.
Zurück zu benutzerdefinierten Gleichheitsvergleichen...
Angenommen, TimeOfAction
ist eine DateTime
oder einen anderen Typ, der einen vernünftigen Hash-Code hat, können Sie Ihre Klasse ändern:
class TimeComparer : IEqualityComparer<Action>
{
public bool Equals(Action a, Action b)
{
return a.TimeOfAction == b.TimeOfAction;
}
public int GetHashCode(Action obj)
{
return obj.TimeOfAction.GetHashCode();
}
}
Beachten Sie, dass ich auch Ihre Equals
Methode - immer dann, wenn Sie sich in einer Situation befinden:
if (condition)
{
return true;
}
else
{
return false;
}
können Sie es vereinfachen:
return condition;