EF代码优先,无法删除外键关系

时间:2013-12-25 07:39:38

标签: c# entity-framework ef-code-first

我在这里显示了两个模型:

public class Application
{
  public string Name { get; set; }
  public virtual ICollection<ApplicationTransaction> ApplicationTransactions { get; set; }
}

public class ApplicationTransaction
{
  public long ApplicationId { get; set; }
  public virtual Application Application { get; set; }
}

我尝试使用以下代码删除ApplicationTransaction的所有Application

var app = _repository.Get<Application>(i => i.Id == 1);
app.ApplicationTransactions.Clear();
Context.SaveChanges();

但是当上下文保存更改时,会发生错误:

  

操作失败:无法更改关系,因为   一个或多个外键属性是不可为空的。当一个   改变了关系,相关的外键属性是   设置为空值。如果外键不支持空值,   必须定义新的关系,外键属性必须是   分配了另一个非空值,或者不相关的对象必须是   删除。

enter image description here

4 个答案:

答案 0 :(得分:1)

我遇到了完全相同的问题,这是解决方案:

技巧:在设置父母和孩子之间的关系时,你必须创建一个&#34;复合&#34;关键的孩子。这样,当您告诉Parent删除其1个或所有子节点时,实际上将从数据库中删除相关记录。

使用Fluent API配置组合键:

modelBuilder.Entity<Child>.HasKey(t => new { t.ParentId, t.ChildId });

然后,删除相关的孩子:

var parent = _context.Parents.SingleOrDefault(p => p.ParentId == parentId);

var childToRemove = parent.Children.First(); // Change the logic 
parent.Children.Remove(childToRemove);

// or, you can delete all children 
// parent.Children.Clear();

_context.SaveChanges();

完成!

答案 1 :(得分:0)

仅清除相关实体的集合是不够的,因为每个相关实体存储指向Application实体的外键;因此,您需要删除相关实体,而不是清除相关实体的集合。

foreach (ApplicationTransaction applicationTransaction in app.ApplicationTransactions.ToList())
    context.DeleteObject(applicationTransaction);

答案 2 :(得分:0)

也许您可以使用Fluent API手动创建关系,如下所示:

 modelBuilder.Entity<Application>()
            .HasOptional(a => a.ApplicationTransactions)
            .WithOptionalPrincipal(a => a.Application);

然后外键列可以为空

答案 3 :(得分:0)

在“保存应用程序”方法中,您可以使用如下逻辑:

var modifiedAppplicationTransactions = context.ChangeTracker.Entries<ApplicationTransactions>().Where(x => x.State == EntityState.Modified);
foreach (var item in modifiedAppplicationTransactions )
{
    if (item.Entity.ApplicationId == null)
    {
        context.Entry(item.Entity).State = EntityState.Deleted;
    }
}
context.SaveChanges():