Entity framework 从收件箱中删除邮件
我首先使用实体框架4.1-代码,我的Entity framework 从收件箱中删除邮件,entity-framework,sql-server-2008,many-to-many,entity-framework-4.1,ef-code-first,Entity Framework,Sql Server 2008,Many To Many,Entity Framework 4.1,Ef Code First,我首先使用实体框架4.1-代码,我的用户和消息实体之间存在多对多关系。该关系通过另一个实体UserMessage映射。我实现的消息传递系统类似于Gmail,这意味着消息是“线程”,其中消息的回复沿着初始消息显示 现在,我正在尝试从用户的收件箱中删除邮件,但我不希望它最终从数据库中删除,因为其他用户可能不会选择从其收件箱中删除邮件。不幸的是,我的代码引发了以下异常: 来自世界各地的关系 “UserMessage\u Receiver”关联开始 处于“已删除”状态。鉴于 多重性约束 相应的 “Use
用户
和消息
实体之间存在多对多关系。该关系通过另一个实体UserMessage
映射。我实现的消息传递系统类似于Gmail,这意味着消息是“线程”,其中消息的回复沿着初始消息显示
现在,我正在尝试从用户的收件箱中删除邮件,但我不希望它最终从数据库中删除,因为其他用户可能不会选择从其收件箱中删除邮件。不幸的是,我的代码引发了以下异常:
来自世界各地的关系
“UserMessage\u Receiver”关联开始
处于“已删除”状态。鉴于
多重性约束
相应的
“UserMessage\u Receiver\u 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);
}
公共类用户消息
{
公共int Id{get;set;}
公共日期时间?上次查看{get;set;}
公共bool IsRead{get;set;}
公共虚拟消息消息{get;set;}
公共虚拟用户发送方{get;set;}
公共虚拟用户接收器{get;set;}
}
public void DeleteFromInbox(int messageId,用户)
{
var message=_repository.First(c=>c.message.Id.Equals(messageId));
var repress=getrepress(用户,messageId);
foreach(回复中的var回复)
{
if(user.ReceivedMessages.Contains(reply))
{
user.ReceivedMessages.Remove(reply);
回复:接收方=null;
}
if(user.SentMessages.Contains(reply))
{
user.SentMessages.Remove(reply);
reply.Sender=null;
}
}
message.Receiver=null;
user.ReceivedMessages.Remove(消息);
}
那么我哪里出错了?从导航属性中删除实体不会将其标记为已删除。它只会删除关系-这意味着
UserMessage
中的FK将设置为null,如果它不可为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
实例,并且除非您将接收者列表存储在其他地方,否则您将丢失一个原始接收者的信息(当发送者从发件箱再次打开消息时,他很可能看不到接收者).var
如果你能从作业的右侧部分看到使用了什么结果类型,那就好了,但是如果是getrepress
我们不知道你返回了什么类型,也不知道你的foreach
删除了什么。@Ladislav Mrnka:它返回了一个IList
:)@Ladislav Mrnka:我也应该删除邮件本身吗?当我这么做的时候,它解决了问题,但是一个新的问题出现了。当我与另一个用户(第一个发送消息的用户)登录时,我得到一个空对象引用异常。。。这就是我试图避免的…@Ladislav Mrnka:那么我必须重新建模整个过程,还是在用户消息中添加“ReceiverName”可以解决问题?另外,我可以通过DataAnnotations使接收方可选,还是需要使用fluent配置?我会将消息信息和收件箱信息分开。将发件人从UserMessage
移动到Message
,并将所有收件人姓名保留为消息中的字符串字段。您的UserMessage
将仅用于单个用户的收件箱建模。如果你从用户那里删除消息,你会删除这个实例,但真正的消息仍然不会被触动。我明白了。但是在这种情况下,EF怎么知道它应该使用UserMessage映射关系而不是自己创建另一个表呢?我是否需要一些配置,或者EF是否足够聪明来解决这个问题?试试看,你会发现。它应该使用您的UserMessage
实体。