C# 删除相关表的多条记录

C# 删除相关表的多条记录,c#,asp.net,asp.net-mvc,entity-framework,C#,Asp.net,Asp.net Mvc,Entity Framework,我的数据库中有两个表,分别是Vendors和VendorPriceBreaks: Vendors ----------------- VendorID (PK) Name VendorPriceBreaks ----------------- VendorPriceBreakID (PK) VendorID (FK) Price 当我删除一个供应商时,我希望所有与之相关的VendorPriceBreak也都被删除。我正在使用实体框架 我先试了一下: public RedirectToRout

我的数据库中有两个表,分别是Vendors和VendorPriceBreaks:

Vendors
-----------------
VendorID (PK)
Name

VendorPriceBreaks
-----------------
VendorPriceBreakID (PK)
VendorID (FK)
Price
当我删除一个供应商时,我希望所有与之相关的VendorPriceBreak也都被删除。我正在使用实体框架

我先试了一下:

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语句与引用约束“FK\u VendorPriceBreaks\u Vendors”冲突。

因此,我在删除对象之前添加了这一行:
vendor.VendorPriceBreaks.Clear()

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


最好的方法是什么?

您可以“包括”您的子实体

var vendor = entities.Vendors
                     .Include("VendorPriceBreaks")
                     .FirstOrDefault(v => v.VendorID == id);
或者,您可以在.edmx设计器中修改两个实体之间关系的属性


您可以“包括”您的子实体

var vendor = entities.Vendors
                     .Include("VendorPriceBreaks")
                     .FirstOrDefault(v => v.VendorID == id);
或者,您可以在.edmx设计器中修改两个实体之间关系的属性


如果您没有在数据库中启用级联删除(我认为这是您的模型中的最佳选择;请参阅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");
}

如果您没有在数据库中启用级联删除(我认为这是您的模型中的最佳选项;请参阅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");
}

我认为你应该创建一个procedor:

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
在您可以将此过程作为函数添加到entityFramwork之后


快乐编码

我认为您应该创建一个处理器:

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
在您可以将此过程作为函数添加到entityFramwork之后


快乐编码

其他人已经提供了有价值的答案,所以你应该选择其中一个作为可接受的答案

我只是加上这个作为答案,因为它太长了,无法评论。通常有四种方法来实现这一点:

Casade删除,如@p.campbell所述。重要的是在数据库中定义对关系的级联删除,以及在EF设计器中定义对关系的
CASCADE
。这就是为什么必须在双方都设置选项的原因

存储过程如@Bilgehan所述。为了防止存储过程在父级之前删除子级。实际上,您可以通过
ExecuteStoreCommand
直接执行SQL

-这是EF中最奇怪的建筑决策之一。它要求子实体具有从其唯一Id和FK到父实体的复合密钥。如果发生这种情况,您只需调用
vendor.VendorPriceBreaks.Clear()
,它不仅会删除关系,还会删除child。缺点是必须从数据库加载相关对象


如@Slauma所述,手动删除相关对象。如果您没有级联删除、存储过程或标识关系,那么就没有其他方法可以加载相关对象并逐个删除它们。

其他人已经提供了有价值的答案,因此您应该选择其中一个作为可接受的答案

我只是加上这个作为答案,因为它太长了,无法评论。通常有四种方法来实现这一点:

Casade删除,如@p.campbell所述。重要的是在数据库中定义对关系的级联删除,以及在EF设计器中定义对关系的
CASCADE
。这就是为什么必须在双方都设置选项的原因

存储过程如@Bilgehan所述。为了防止存储过程在父级之前删除子级。实际上,您可以通过
ExecuteStoreCommand
直接执行SQL

-这是EF中最奇怪的建筑决策之一。它要求子实体具有从其唯一Id和FK到父实体的复合密钥。如果发生这种情况,您只需调用
vendor.VendorPriceBreaks.Clear()
,它不仅会删除关系,还会删除child。缺点是必须从数据库加载相关对象


如@Slauma所述,手动删除相关对象。如果没有级联删除、存储过程或标识关系,则没有其他方法可以加载相关对象并逐个删除它们。

删除顺序应颠倒。您必须先删除从属记录,然后才能删除父记录。uppss:)我知道,很抱歉,删除顺序应该颠倒。您必须先删除从属记录,然后才能删除父记录。uppss:)我知道,很抱歉