Ваши методы Equals и GetHashCode используют полностью различных подходов. В частности, одинаковые объекты могут иметь разные хеш-коды, предполагая, что Action.ToString
использует поля, отличные от TimeOfAction. Они должны быть согласованы, иначе у вас не будет абсолютно никаких шансов получить разумные результаты. Это нормально для неравных объектов иметь одинаковый хэш-код (хотя это будет снижать производительность), но равные объекты должны давать тот же хеш-код.
Обратите внимание, что использование пользовательского компаратора заставит часть Distinct выполняться не в базе данных, а в процессе. Это может не быть проблемой, вам просто нужно это понять. РЕДАКТИРОВАТЬ: я не заметил, что есть перегрузка Queryable.Distinct
, что делает принять IEqualityComparer<T>
. Я предполагаю, что это так, что вы можете предоставить пользовательские компараторы строк и несколько других известных компараторов ... не просто произвольный код. Если это работает, это все равно будет сделано локально. Я не удивлюсь, если он просто взорвется.
РЕДАКТИРОВАТЬ: Как говорит Марк, вы можете использовать Select(x => x.TimeOfAction).Distinct().Count()
, чтобы сделать это в базе данных. Вам также нужно будет удалить вызов на AsEnumerable
. Я думаю, что это там, потому что что-то еще не работает. Вы можете попробовать это:
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();
Конечно, если вам нужно query
для чего-то другого, вам также нужно сохранить оригинальную версию:
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
Обратите внимание, что при повторном использовании запроса будет произведен второй запрос к базе данных. Вам нужно посмотреть, что происходит с точки зрения транзакций, если вам нужно, чтобы количество соответствовало тому, что делает второй запрос ... или извлекать все детали из базы данных (используя вызов ToList
), а затем выполнить Отдельная часть в процессе.
Вернуться к пользовательским компараторам равенства ...
Предполагая, что TimeOfAction
- это DateTime
или какой-либо другой тип, имеющий разумный хэш-код, вы можете изменить свой класс на:
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();
}
}
Обратите внимание, что я также упростил ваш метод Equals
- каждый раз, когда вы обнаруживаете:
if (condition)
{
return true;
}
else
{
return false;
}
Вы можете упростить это до:
return condition;