Сообщение появляется несколько раз внутри папки "Входящие"

У меня есть система личных сообщений, которая больше похожа на стиль Google Mail. Я имею в виду, что сообщения сгруппированы в разговоры. Если пользователь получает сообщение, оно появляется в его почтовом ящике. Кроме того, этот пользователь отправляет сообщение кому-то, кто, в свою очередь, отвечает, тогда это сообщение также появляется в его почтовом ящике.

Некоторые сообщения извлекаются в обоих запросах, которые в конечном итоге группируются в один список. Я попытался удалить дубликаты, выполнив то, что сделал Джон Скит в удалении дубликатов из списка C # но, тем не менее, я продолжаю получать дубликаты. Вот мой код:

ОБНОВЛЕНО:

public class Message : IEquatable<Message>
{
    public int Id { get; set; }
    [MaxLength(150)]
    public string Subject { get; set; }
    [MaxLength(3000)]
    public string Content { get; set; }
    public DateTime DateSent { get; set; }
    public DateTime? LastViewed { get; set; }
    public bool IsRead { get; set; }
    public bool DisplayInInbox { get; set; }
    public virtual User SentBy { get; set; }
    public virtual User ReceivedBy { get; set; }
    public int? ParentId { get; set; }

    public override bool Equals(object other)
    {
        return Equals(other as Message);
    }

    public bool Equals(Message other)
    {
        if (object.ReferenceEquals(other, null))
        {
            return false;
        }
        if (object.ReferenceEquals(other, this))
        {
            return true;
        }
        return Id == other.Id;
    }

    public override int GetHashCode()
    {
        return this.Id;
    }
}

// внутри MessagingService public IList GetThreads (User user) {// Получить все сообщения, на которые нет ответов. var tmp = _repository.GetMany (c => c.DisplayInInbox.Equals (true) && c.ParentId.Equals (null)); var thread = (из c в tmp, где GetReplies (user, c.Id) .Count ()> 0 выберите c) .ToList (); var threadByUser = user.ReceivedMessages.Where (m => m.DisplayInInbox.Equals (true) && m.ParentId.Equals (null)). ToList (); threads.AddRange (threadByUser); Threads.Distinct (). ToList (); возвращать потоки; }

Я что-то здесь делаю не так?


person Kassem    schedule 26.04.2011    source источник


Ответы (3)


В обоих DTO вы реализовали GatHashcode. Разве вы не должны использовать их при проверке равенства?

return Id == other.Id && Subject == other.Subject && SentBy.Nickname == other.SentBy.Nickname &&
           DateSent == other.DateSent;

return Id == other.Id && Subject == other.Subject && Sender == other.Sender;

стать

return GetHashCode() == other.GetHashCode()

РЕДАКТИРОВАТЬ:

Я тоже немного придираюсь ... не переопределяйте / не перегружайте метод equals. Это метод equals, который использует GetHashcode для определения равенства. Вы перегрузили equals, чтобы поймать DTO, который по умолчанию сравнивал бы результат GetHashcode для обоих объектов. Ваша перегруженная версия не сравнивает хэш-код, что делает его избыточным, хотя на самом деле он выглядит как правильная реализация.

РЕДАКТИРОВАТЬ 2 (в ответ на изменения кода в вашем сообщении): трудно сказать, потому что раздел кода в нижней части вашего сообщения не отформатирован, а от предпоследней строки:

threads.Distinct().ToList();
return threads;

Это ничего не делает. Объедините два:

return threads.Distinct().ToList();
person Smudge202    schedule 26.04.2011
comment
Я удалил код из DTO. Теперь все лежит в классах сущностей. - person Kassem; 26.04.2011
comment
Если удаление перегрузки equals не решает вашу проблему, значит, проблема связана с вашим хэш-кодом и, следовательно, с небольшими различиями между полями. @ A.R. наверное, самый близкий ответ (+1 к вам А.Р.) - person Smudge202; 26.04.2011
comment
На самом деле я использую @ A.R. реализация сейчас. Я действительно удивлен, что это все еще не работает. Может быть, вызов .Distinct() не выполняет то, что должен? - person Kassem; 26.04.2011
comment
@Kassem Я отредактировал свой ответ. В значительной степени игнорируйте первую часть ... см. После EDIT 2. - person Smudge202; 26.04.2011
comment
+1 !! Это на самом деле сработало! Я думал, что метод Distinct () выполняет свою работу, думаю, нет ... Спасибо за помощь, я благодарен :) - person Kassem; 26.04.2011

Не предоставляя нам никаких примеров ваших повторяющихся сообщений, которые не удаляются, я собираюсь предположить, что ваше использование DateTime в вашем коде проверки равенства является вероятным виновником. Очень часто и легко написать что-то вроде 'SentDate = DateTime.Now;', что впоследствии запутает систему. Это всего лишь предположение.

Между тем я бы предположил, что ваши функции равенства и хэш-кода находятся на грани излишества. Теперь я собираюсь предположить, что «ID» для классов Message и MessageThread должен быть уникальным, и в этом случае вы действительно можете упростить свою логику и легче разобраться в сути своей проблемы, например:

public override bool Equals(object other)
{
    return Equals(other as Message);
}

public bool Equals(Message other)
{
  if (other == null) { return false; }
  return this.Id == other.Id;
}

public override int GetHashCode()
{
  // If the ID is unique, then it satisfied the purpose of 'GetHashCode'
  return this.Id;
}

Очевидно, вы захотите сделать это и для других классов. Преимущество здесь в том, что здесь меньше движущихся частей и, следовательно, меньше возможностей для того, чтобы что-то пошло не так. Кроме того, вам не нужны тела сообщения, отправители и т. Д. Для определения уникальности сообщения.

person A.R.    schedule 26.04.2011
comment
Я изменил свой код, чтобы использовать вашу реализацию, и очень тщательно отладил его. Думаю, проблема не в коде сравнения. Может быть .Distinct () не выполняет свою работу? Я также попытался использовать .Union (), но это исключило одно из сообщений, хотя это не должно было быть. В настоящее время код возвращает три сообщения (потока), которые, если он работал правильно, должны возвращать только 2, потому что два из них имеют одинаковый идентификатор (значение = 1). - person Kassem; 26.04.2011

Это нормально?

return Id == other.Id && Subject == other.Subject && SentBy.Nickname == other.SentBy.Nickname &&
               DateSent == other.DateSent;

Я бы предпочел подход, при котором если id равен, почтовые сообщения такие же:

return Id == other.Id;
person VikciaR    schedule 26.04.2011