C# 删除相关表的多条记录
我的数据库中有两个表,分别是Vendors和VendorPriceBreaks: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
-----------------
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:)我知道,很抱歉