我正在使用Entity Framework 4.1 - Code First,我的User
和Message
实体之间有很多关系。该关系通过另一个实体UserMessage
映射。我实现的消息系统类似于Gmail的消息系统,这意味着消息是“线程”,其中消息的回复显示在初始消息中。
现在我正在尝试从用户的收件箱中删除邮件,但我不希望它最终被从数据库中删除,因为其他用户可能不会选择从他/她的收件箱中删除邮件。不幸的是,我的代码抛出了以下异常:
来自的关系 'UserMessage_Receiver'AssociationSet 处于'已删除'状态。特定 多重约束,a 相应 'UserMessage_Receiver_Source'必须 也处于'已删除'状态。
以下是涉及的代码:
public class UserMessage
{
public int Id { 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 void DeleteFromInbox(int messageId, User user)
{
var message = _repository.First<UserMessage>(c=>c.Message.Id.Equals(messageId));
var replies = GetReplies(user, messageId);
foreach (var reply in replies)
{
if (user.ReceivedMessages.Contains(reply))
{
user.ReceivedMessages.Remove(reply);
reply.Receiver = null;
}
if (user.SentMessages.Contains(reply))
{
user.SentMessages.Remove(reply);
reply.Sender = null;
}
}
message.Receiver = null;
user.ReceivedMessages.Remove(message);
}
那我哪里出错了?
答案 0 :(得分:1)
从导航属性中删除实体不会将其标记为已删除。它只会删除关系 - 这意味着UserMessage
中的FK将被设置为null,如果它不可为空,您将获得异常。你必须做类似的事情:
foreach (var reply in replies)
{
if (user.ReceivedMessages.Contains(reply))
{
user.ReceivedMessages.Remove(reply);
reply.Receiver = null;
}
if (user.SentMessages.Contains(reply))
{
user.SentMessages.Remove(reply);
reply.Sender = null;
}
_repository.Delete(reply);
}
编辑:
上述代码删除了UserMessage
- 而不是Message
。当我考虑你的模型时,你的新问题是显而易见的。您的第一个例外是由UserMessage
实体的多重约束引起的 - Receiver
是强制性的,因此您无法在不删除整个UserMessage
的情况下删除与接收者的关系,但一旦删除UserMessage
(和消息没有其他接收者)它也会从发送者中删除它。
你的模特错了。即使您使Receiver
成为可选项,也会导致UserMessage
个实例没有接收者,除非您在其他地方存储接收者列表,否则您将丢失有关原始接收者之一的信息(当发件人再次从他的发件箱打开邮件时很可能不会看到接收器。