关系删除时移除依赖实体
本文关键字:依赖 实体 删除 关系 | 更新日期: 2023-09-27 18:08:02
假设我有两个实体:
public class Response
{
public int Id { get; set; }
public int PatientId { get; set; }
public virtual Patient Patient { get; set; }
public string Text { get; set; }
}
public class Patient
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Response> Responses { get; set; }
}
我想要能够调用
Patient.Responses.Remove(someResponse);
并让实体不仅删除关系,而且删除响应实体。目前,如果我只是删除关系,我得到以下错误:
系统。InvalidOperationException:操作失败:不能更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性被设置为空值。如果外键不支持空值,则必须定义一个新的关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。
阅读这篇博客文章http://blogs.msdn.com/b/dsimmons/archive/2010/01/31/deleting-foreign-key-relationships-in-ef4.aspx我意识到我可以通过以下映射来实现这一点:
modelBuilder.Entity<Response>().HasKey(m => new { m.Id, m.PatientId });
但是我不想改变主键。我要做的是重写DbContext.SaveChanges(),并将删除Patient关系的任何响应标记为删除。我试过了:
public override int SaveChanges()
{
// Need to manually delete all responses that have been removed from the patient, otherwise they'll be orphaned.
var orphanedResponses = ChangeTracker.Entries().Where(
e => e.State == EntityState.Modified &&
e.Entity is Response &&
e.Reference("Patient").CurrentValue == null);
foreach (var orphanedResponse in orphanedResponses)
{
Responses.Remove(orphanedResponse.Entity as Response);
}
return base.SaveChanges();
}
但是我发现可以只附加Response。设置PatientId而不是Response。病人,实体没有加载响应。所以我的代码认为它是孤立的,应该被删除。
总之
我想知道的是我怎样才能知道一个实体已经被修改了,因为它的FK关系已经被删除了
用这个代替:
public override int SaveChanges()
{
var responses = Responses.Local.Where(r => r.Patient == null);
foreach (var response in responses.ToList())
{
Responses.Remove(response);
}
return base.SaveChanges();
}
您需要配置映射,以便发生级联删除。要做到这一点,您需要将具有WillCascadeOnDelete
的模型映射到true
。
public class MyContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Patient>()
.HasMany(patient=> patient.Responses)
.WithRequired(response => response.Patient)
.HasForeignKey(response => response.PatientId)
.WillCascadeOnDelete(true);
}
}
我认为我的问题不是代码,而是我如何假设实体的Attach()方法工作。我假设如果我附加一个带有PatientId集合但没有Patient属性的响应,那么实体将为我填充Patient属性。
事实上,我认为发生的是实体附加它,然后如果我将该实体标记为已修改并保存它,实体看到null Patient属性并假设我想要删除关系,因此抛出一个错误,因为它将被孤立(不能null Response.PatientId)。因此,也许一切都按照设计工作,并且我的SaveChanges()解决方案工作。