Ваши Equals и методы GetHashCode принимают полностью разные подходы. В частности, равные объекты могут иметь разные хэш-коды, предполагая, что Action.ToString
использует поля, отличные от TimeOfAction. Они должны быть выровнены, или у вас не будет абсолютно никаких шансов получить разумные результаты. Это нормально для неравных объектов иметь один и тот же хэш-код (хотя это будет препятствовать производительности), но равные объекты должен дать тот же хеш-код.
Обратите внимание, что использование настраиваемого компаратора приведет к тому, что отличительная часть будет выполняться в процессе, а не в базе данных. Это может не быть проблемой, вам просто нужно это понять. EDIT: я не заметил, что есть перегрузка Queryable.Distinct
, которая делает принимает IEqualityComparer<T>
. Я предполагаю, что вы можете предоставить пользовательские сопоставления строк и несколько других известных компараторов ... а не только произвольный код. Если это сработает, все равно это будет сделано локально. Я бы не удивился, если бы он просто взорвался.
EDIT: Как говорит Марк, вы можете использовать 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
), а затем сделать Distinct часть в процессе.
Назад к пользовательским сравнительным анализаторам ...
Предполагая 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;
Хорошая деталь (по-прежнему использует 'IEnumerable <>' хотя?). –
@Marc: Ой, да :) –