我的数据库中有这两个表,名为Vendors和VendorPriceBreaks:
Vendors
-----------------
VendorID (PK)
Name
VendorPriceBreaks
-----------------
VendorPriceBreakID (PK)
VendorID (FK)
Price
当我删除供应商时,我希望删除与之关联的所有VendorPriceBreaks。我正在使用实体框架。
我先试了这个:
public RedirectToRouteResult Delete(int id)
{
MyEntities entities = new MyEntities();
var vendor = entities.Vendors.FirstOrDefault(v => v.VendorID == id);
entities.Vendors.Context.DeleteObject(vendor);
entities.Vendors.Context.SaveChanges();
return RedirectToAction("Index");
}
这给了我错误消息: DELETE语句与REFERENCE约束“FK_VendorPriceBreaks_Vendors”冲突
然后我在删除对象之前添加了这一行:vendor.VendorPriceBreaks.Clear();
但后来我收到此错误消息:操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。
最好的方法是什么?
答案 0 :(得分:2)
您可以“包含”您的子实体。
var vendor = entities.Vendors
.Include("VendorPriceBreaks")
.FirstOrDefault(v => v.VendorID == id);
或者,您可以修改.edmx设计器中2个实体之间关系的属性。
答案 1 :(得分:1)
如果您没有在数据库中启用级联删除(我认为这是模型中的最佳选项;请参阅p.campbell的回答),您必须明确删除集合中的项目:
public RedirectToRouteResult Delete(int id)
{
MyEntities entities = new MyEntities();
var vendor = entities.Vendors.FirstOrDefault(v => v.VendorID == id);
foreach (var item in vendor.VendorPriceBreaks.ToList())
entities.VendorPriceBreaks.Context.DeleteObject(item);
entities.Vendors.Context.DeleteObject(vendor);
entities.Vendors.Context.SaveChanges();
return RedirectToAction("Index");
}
答案 2 :(得分:1)
我认为你应该创建一个程序:
Create proc DeleteRecords
@VendorID int
As
BEGIN TRY
BEGIN TRAN
DELETE FROM VendorPriceBreaks
WHERE VendorID =@VendorID
DELETE FROM Vendors
WHERE VendorID =@VendorID
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRAN
END CATCH
之后,您可以将此proc作为函数添加到您的实体框架中。
快乐编码
答案 3 :(得分:1)
其他人已经提供了有价值的答案,因此您应该选择他们作为可接受的答案。
我只是将其添加为答案,因为评论太长了。通常有四种方法可以实现这一目标:
@p.campbell描述的Casade删除。重要的是在数据库中的关系上定义ON CASCADE DELETE,在EF设计器中定义关于Cascade
的关系。 Here是必须在双方都设置选项的原因。
@Bilgehan描述的存储过程。只是在存储过程的情况下删除父项之前的子项。您实际上可以通过ExecuteStoreCommand
直接执行SQL。
Identifying relation - 这是EF中最奇怪的建筑裁员之一。它要求子实体具有从其唯一Id和FK到父级的组合键。如果发生这种情况,您可以简单地调用vendor.VendorPriceBreaks.Clear()
,它不仅会删除关系,还会删除子项。缺点是必须从数据库加载相关对象。
按照@Slauma的描述手动删除相关对象。如果您没有级联删除,存储过程或识别关系,则没有其他方法可以加载相关对象并逐个删除它们。