说我有两个这样的实体:
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);
让实体不仅删除关系,还删除Response实体。目前,如果我删除该关系,我会收到以下错误:
System.InvalidOperationException:操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为foreign-key属性分配另一个非空值,或者必须删除不相关的对象。
阅读此博客文章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()并标记删除任何已删除患者关系的响应。我试过这个:
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.Patient的响应,实体不会加载Response.Patient属性,所以我的代码认为它已经被孤立并且应该被删除。
总结
我想知道的是,如何修改实体,因为它的FK关系已被删除。
答案 0 :(得分:2)
请改用:
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();
}
答案 1 :(得分:1)
您需要配置映射,以便进行级联删除。为此,您需要将模型与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);
}
}
答案 2 :(得分:1)
我认为我的问题不在于代码,而在于我假设实体的Attach()方法是如何工作的。我假设如果我附加了PatientId设置而不是Patient属性的响应,那么实体将为我填充Patient属性。
实际上我认为发生的是实体按原样附加它,然后如果我将该实体标记为已修改并保存它,实体将看到null Patient属性并假设我想要删除该关系,因此抛出错误,因为它将是孤立的(不能为null Response.PatientId)。所以也许一切都按设计工作,我的SaveChanges()解决方案也可以。