删除相关表的多个记录

时间:2011-04-10 20:27:35

标签: c# asp.net asp.net-mvc entity-framework

我的数据库中有这两个表,名为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();

但后来我收到此错误消息:操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

最好的方法是什么?

4 个答案:

答案 0 :(得分:2)

您可以“包含”您的子实体。

var vendor = entities.Vendors
                     .Include("VendorPriceBreaks")
                     .FirstOrDefault(v => v.VendorID == id);

或者,您可以修改.edmx设计器中2个实体之间关系的属性。

enter image description here

答案 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的描述手动删除相关对象。如果您没有级联删除,存储过程或识别关系,则没有其他方法可以加载相关对象并逐个删除它们。