#entity-framework #entity-framework-4 #many-to-many #entity-relationship
#entity-framework #entity-framework-4 #»многие ко многим» #сущность-взаимосвязь
Вопрос:
По какой-то причине я не могу разобраться с этим… У меня есть система личных сообщений, которая позволяет пользователям отправлять друг другу личные сообщения. Пользователь также может удалить сообщение из своего почтового ящика, но когда это произойдет, его не следует удалять из почтового ящика другого пользователя. Для этого, я полагаю, у меня должно быть отношение «многие ко многим» между объектами User и Message. Но как я должен сопоставить это отношение, чтобы позволить пользователям удалять сообщения из своего почтового ящика (для которого, как я думал, я создам логическое значение: DisplayInInbox) и не удалять его также из папки «Входящие» другого пользователя?
Моя текущая модель, которая не работает, заключается в следующем:
public class 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 int? ParentId { get; set; }
}
и в классе user у меня есть это свойство:
public virtual ICollection<Message> ReceivedMessages { get; set; }
Нужны ли мне два логических значения или одного будет достаточно? И как мне в конечном итоге отобразить это отношение?
Обновить:
Хорошо, теперь вот моя модель:
public class Inbox
{
[Key, Column(Order = 0), ForeignKey("User")]
public int UserId { get; set; }
[Key, Column(Order = 1), ForeignKey("Message")]
public int MessageId { get; set; }
public DateTime? LastViewed { get; set; }
public bool IsRead { get; set; }
public virtual Message Message { get; set; }
public virtual User Sender { get; set; }
public virtual User Receiver { get; set; }
}
public class 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 int? ParentId { get; set; }
public virtual ICollection<Inbox> ReceivedBy { get; set; }
public virtual ICollection<Inbox> SentBy { get; set; }
}
И в классе User:
public virtual ICollection<Inbox> ReceivedMessages { get; set; }
Ответ №1:
Вам не нужно никакого логического значения. Значение boolean — это то, что вы на самом деле моделируете отношением «многие ко многим». У вас будет сообщение в базе данных только один раз, а присутствие входящих сообщений будет определяться отношением «многие ко многим».
Проблема в том, что вы хотите сохранить некоторую дополнительную информацию, связанную с сообщением и пользователем. Из-за этого вы должны предоставить таблицу соединений как отдельный объект:
// The message
public class 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; }
[ForeignKey("ParentMessage")]
public int? ParentId { get; set; }
[ForeignKey("Sender")]
public int SenderId { get; set; }
...
public virtual Message ParentMessage { get; set; }
public virtual ICollection<Inbox> ReceivedBy { get; set; }
public virtual User Sender { get; set; }
}
public class Inbox
{
[Key, Column(Order = 0), ForeignKey("User")]
public int UserId { get; set; }
[Key, Column(Order = 1), ForeignKey("Message")]
public int MessageId { get; set; }
public DateTime? LastViewed { get; set; }
public bool IsRead { get; set; }
public virtual Message Message { get; set; }
public virtual User User { get; set; }
}
public class User
{
public int Id { get; set; }
...
public virtual ICollection<Inbox> ReceivedMessages { get; set; }
public virtual ICollection<Message> SendMessages { get; set; }
}
Теперь удаление сообщения из папки «Входящие» пользователя просто означает удаление записи из ReceivedMessages
, но это не приведет к удалению сообщения — это приведет только к удалению записи в Inbox
таблице.
Редактировать:
Я обновил пример кода, чтобы поддерживать все ваши дополнительные требования. Теперь:
- У каждого
Message
может быть несколько получателей - Получение
Message
выполняется отдельным объектом, вызываемымInbox
, который позволит вам удалять сообщения для каждогоUser
и использовать такие свойства, какIsRead
perUser
. Message
имеет необязательныйParentId
иParentMessage
, поэтому вы можете отслеживать реакции на другие сообщения.Message
имеетSender
иSenderId
и в то же времяUser
имеет коллекцию отправленных сообщений. На мой взгляд, aMessage
отправляется однимUser
, поэтому это отношение не имеет ничего общего сInbox
и должно быть непосредственно междуMessage
иUser
.
Комментарии:
1. @Ladislav Mrnka: Отлично! Именно то, что я искал! Теперь мне нужно провести серьезный рефакторинг в моей системе PM… Спасибо за помощь! 🙂
2. @Ladislav Mrnka: Я думаю, что одной вещи все еще не хватает… Мне нужно знать, кто отправил сообщение и кто его получил. Ваш код показывает только, кто его получил, верно?
3. и еще одна вещь… предполагается, что это скорее система PM, похожая на переписку … это стиль «Google Mail», где, когда вы отвечаете на электронное письмо, оно отображается прямо под ним в том же разговоре. И именно поэтому я использую поле «ParentID»… Я предполагаю, что когда ParentID равен null, это означает, что это сообщение является ответом, а не новым потоком…
4. @Kassem: Все это можно решить. Добавить
Sender
как отношение кMessage
и использоватьParentId
для построения иерархии сообщений.5. @Ladislav Mrnka: Я обновил свой пост. Я думаю, так и должно быть, верно?