我在这里显示了两个模型:
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();
但是当上下文保存更改时,会发生错误:
操作失败:无法更改关系,因为 一个或多个外键属性是不可为空的。当一个 改变了关系,相关的外键属性是 设置为空值。如果外键不支持空值, 必须定义新的关系,外键属性必须是 分配了另一个非空值,或者不相关的对象必须是 删除。
答案 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():