简体   繁体   English

删除相关表的多个记录

[英]Deleting multiple records for a related table

I have these two tables in my database, named Vendors and VendorPriceBreaks: 我的数据库中有两个表,分别名为Vendors和VendorPriceBreaks:

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

VendorPriceBreaks
-----------------
VendorPriceBreakID (PK)
VendorID (FK)
Price

When I delete a Vendor, I'd like to have all the VendorPriceBreaks associated with it deleted as well. 当我删除供应商时,我也想删除与其关联的所有VendorPriceBreaks。 I'm using Entity Framework. 我正在使用实体框架。

I tried this first: 我首先尝试了这个:

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");
}

Which gave me the error message: The DELETE statement conflicted with the REFERENCE constraint "FK_VendorPriceBreaks_Vendors" 这给了我错误消息: DELETE语句与REFERENCE约束“ FK_VendorPriceBreaks_Vendors”冲突

So then I added this line before I deleted my object: vendor.VendorPriceBreaks.Clear(); 因此,在删除对象之前,我添加了以下行: vendor.VendorPriceBreaks.Clear();

But then I got this error message: The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. 但是,然后我收到此错误消息: 操作失败:由于一个或多个外键属性不可为空,因此无法更改该关系。 When a change is made to a relationship, the related foreign-key property is set to a null value. 对关系进行更改时,相关的外键属性将设置为空值。 If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted. 如果外键不支持空值,则必须定义新的关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

What's the best way to do this? 最好的方法是什么?

You could 'include' your child entities. 您可以“包括”您的子实体。

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

Alternatively, you can modify a property on the relationship between your 2 entities in the .edmx designer. 或者,您可以在.edmx设计器中修改两个实体之间关系的属性。

在此处输入图片说明

If you don't have enabled cascading delete in the database (which would be best option in your model, I think; see p.campbell's answer) you have to delete the items in the collection explicitely: 如果您尚未在数据库中启用级联删除(我认为这是您模型中的最佳选择;请参阅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");
}

I think you should create a 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

And after you can add this proc to your entityFramwork as a function. 然后,您可以将此proc作为函数添加到您的entityFramwork中。

happy coding 快乐编码

Other guys have already provided valuable answers so you should select on of them as accepted answers. 其他人已经提供了有价值的答案,因此您应该选择其中一个作为接受的答案。

I'm just adding this as answer because it is too long for comment. 我只是将其添加为答案,因为评论太长了。 There are generally four ways to achieve this: 通常有四种方法可以实现此目的:

Casade delete as described by @p.campbell. Casade按照@ p.campbell的说明删除。 The important is to define ON CASCADE DELETE on relation in database as well as Cascade on relation in EF designer. 重要的是在数据库中的关系上定义ON CASCADE DELETE以及在EF设计器中在关系上定义Cascade Here is a reason why the option must be set on both sides. 是为什么必须在两侧都设置该选项的原因。

Stored procedure as described by @Bilgehan. 如@Bilgehan所述的存储过程。 Just in case of stored procedure delete childs before the parent. 以防万一存储过程中删除父级之前的子级。 You can actually execute SQL directly by ExecuteStoreCommand . 实际上,您可以直接通过ExecuteStoreCommand执行SQL。

Identifying relation - this is one of the strangest architecutre decissions in EF. 识别关系 -这是EF中最奇怪的建筑决定之一。 It requires that child entity has composite key from its unique Id and FK to parent. 它要求子实体具有从其唯一ID和FK到父代的复合键。 If this happens you can simply call vendor.VendorPriceBreaks.Clear() and it will not only remove relations but also deletes childs. 如果发生这种情况,您可以简单地调用vendor.VendorPriceBreaks.Clear() ,它不仅会删除关系,还会删除子项。 The disadvantage is that related objects must be loaded from database. 缺点是必须从数据库中加载相关对象。

Manual deletion of related objects as described by @Slauma. 手动删除相关对象,如@Slauma所述。 If you don't have cascade delete, stored procedure or identifying relation there is no other way then load related objects and delete them one by one. 如果没有级联删除,存储过程或标识关系,则没有其他方法可以加载相关对象并逐个删除它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM