2015-11-25 108 views
1

我试图删除Invoice以及任何相关CostsInvoiceCosts是一对多关系。实体框架无法完成删除

我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从表中删除。

Invoice有相关Costs,但是,它引发以下错误:

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

回答

-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标准做法。

0

您可以将删除发票移至循环之后吗? 例如: -

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); 
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费用也将被删除。

+0

同意,除非我将它保留在实体框架中,因此丢弃的数据库将重建它与级联。看到这个SO:http://stackoverflow.com/questions/17487577/entity-framework-ef-code-first-cascade-delete-for-one-to-zero-or-one-relations – MutantNinjaCodeMonkey

+0

非常真实,无论哪种方式完成同样的事情。这完全取决于您是否需要与数据库进行所有交互来进行级联。 –

+0

@MutantNinjaCodeMonkey我从现有的数据库实现中首先使用代码。最好的做法是按照SO链接中描述的方式设置级联,或者是Matt的SQL本质上是做同样的事情,也许是更干净的方法? – KidBatman

0

如果模型正确设置,以便它知道你有一个外键约束,相信你真正需要做的是确保EF拥有所有的相关信息删除之前,像这样:

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