之前可能会问过,但我似乎无法在网站上找到解决方案,所以我们走了:
以下是我的域模型的过度简化版本。我有2个类代表数据库中的2个表:
public Class Person
{
public int Id { get; set;}
public string Name { get; set;}
public virtual List<Contact> Contacts { get; set;}
public void AddContact(string value)
{
//some validation code
Contacts.Add(new Contact(value));
}
public void DeleteContact(Contact contact)
{
//some validation code
Contacts.Remove(contact);
}
}
public Class Contact
{
public int Id { get; set;}
public string Value { get; set;}
public virtual Person Person { get; set;}
public int PersonId { get; set;}
}
现在Person是我的聚合根。我试图通过仅为聚合根创建存储库来遵循DDD主体。添加联系人工作正常。
我遇到的问题是删除联系人时。它给出了错误:
操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。
反正过去了吗?如果关系属性不可为空,那么实体框架不应自动删除联系人。
现在我知道从集合中删除与从上下文中删除它不同,但我不想从我的域模型中引用DbContext。
我只有PersonRepository。
请提供解决方案或帮助我理解我是否有任何错误概念。
答案 0 :(得分:1)
您似乎遇到与this post相同的问题。基本上,当你从集合中删除联系人时,你实际上并没有删除它;你只是孤立它,并在此过程中,将其PersonId设置为null
(当然,int
是不可能的。)
一种可能的解决方案是在Contact类中使PersonId可以为空:
public int? PersonId { get; set; }
然后,在您的DbContext中,覆盖SaveChanges
以自动删除孤立记录:
public override int SaveChanges()
{
foreach (Contact contact in Contacts.Local.Where(c => c.PersonId == null))
{
Contacts.Remove(contact);
}
return base.SaveChanges();
}
免责声明:我还没有对该代码进行测试,但希望这是一个很好的起点。
答案 1 :(得分:1)
使用EF进行DDD时,这是一个常见问题。到目前为止,有两种解决方案对我有用:
从DeleteContact
方法返回已删除的实例。该方法很可能是从拥有存储库的应用程序服务调用的。然后,您可以使用它从DbContext中删除实例。
如果您使用domain events,则可以使用其中一个通知其他人有关联系人移除的信息。然后,您可以在基础结构层中放置此事件的处理程序,这将从DbContext中删除联系人。