实体框架无法完成删除

时间:2015-11-25 23:41:23

标签: c# entity-framework linq

我正在尝试删除Invoice以及任何相关的CostsInvoiceCosts是一对多关系。

My Snipp:

Invoice invoiceToDelete = db.Invoices.First(i => i.Id == id);
db.Invoices.Remove(invoiceToDelete);

var costs = db.Costs.Where(i => i.InvoiceId == id);

foreach (var cost in costs)
{
    //Delete all related costs.
    db.Costs.Remove(cost);
}

//Tried using this as well to try and delete all related costs
//db.Costs.RemoveRange(db.Costs.Where(x => x.InvoiceId == id));

db.SaveChanges();

如果Invoice没有相关的Costs,则代码执行正常,Invoice将从表中删除。

但是当InvoiceCosts相关时,会引发以下错误:

The DELETE statement conflicted with the REFERENCE constraint "FK_Costs_Invoices". The conflict occurred in database "MyDB", table "dbo.Costs", column 'InvoiceId'. The statement has been terminated.

在SSMS中编写删除SQL语句,我可以根据Costs的外键从InvoiceId表中删除。

4 个答案:

答案 0 :(得分:1)

完成此操作的最佳方法是在数据库中添加级联删除。您很可能有一个简单的外键约束。您将需要删除该约束并在删除时使用级联再次添加它。

完成此操作的语句如下所示:

ALTER TABLE dbo.Costs
   DROP CONSTRAINT FK_Invoices_Costs --name of constraint

ALTER TABLE dbo.Costs
   ADD CONSTRAINT FK_Invoices_Costs_Cascade
   FOREIGN KEY (InvoiceId) REFERENCES dbo.Invoices(InvoiceId) ON DELETE CASCADE

完成此设置后;使用EF删除的发票的InvoiceId的所有费用也将被删除。

答案 1 :(得分:0)

您可以将删除发票移动到循环后吗? e.g:

var costs = db.Costs.Where(i => i.InvoiceId == id);

foreach (var cost in costs)
{
    //Delete all related costs.
    db.Costs.Remove(cost);
}
db.Invoices.Remove(invoiceToDelete);

答案 2 :(得分:0)

如果您的模型设置正确,以便它知道您有外键约束,我相信您真正需要做的就是确保EF在删除之前拥有所有相关信息,如下所示:

Invoice invoiceToDelete = db.Invoices.Include(i=>i.Costs).First(i => i.Id == id);
db.Invoices.Remove(invoiceToDelete);
db.SaveChanges();

答案 3 :(得分:-1)

不幸的是,这些建议都没有适用于我的情况。我的工作是使用两个不同的DbContext实例进行更改,以对Invoices和{}进行更改。分别为Costs

using (var ctx = new MyDbContext())
{
      //Delete Invoice
      ctx.SaveChanges();
}

using (var ctx = new MyDbContext())
{
      //Delete related costs
      ctx.SaveChanges();
}

非常感谢Matt Rowland。他的答案可能是更合适的解决方案,但不幸的是,无论出于何种原因,我无法为我的特定实例工作。我正在处理的sln最初是由顾问开发的,他们可能没有遵守EF标准做法。