我编辑了整个问题,因为我设法找到触发错误的原因,所以我只保留了SQL方法,因为它很容易测试
可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY 约束。
DROP TABLE dbo.ProductionUnits
CREATE TABLE ProductionUnits
(
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(50)
)
DROP TABLE Cells
CREATE TABLE Cells
(
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(10),
ProductionUnitId INT FOREIGN KEY REFERENCES ProductionUnits(Id) ON DELETE CASCADE ON UPDATE CASCADE
)
DROP TABLE CheckLists
CREATE TABLE CheckLists
(
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(20),
CellId INT FOREIGN KEY REFERENCES Cells(Id) ON DELETE CASCADE ON UPDATE CASCADE
)
DROP TABLE CheckListGroups
CREATE TABLE CheckListGroups
(
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(20),
CheckListId INT FOREIGN KEY REFERENCES CheckLists(Id) ON DELETE CASCADE ON UPDATE CASCADE
)
DROP TABLE CheckListGroupItems
CREATE TABLE CheckListGroupItems
(
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(20),
CheckListGroupId INT FOREIGN KEY REFERENCES CheckListGroups(Id) ON DELETE CASCADE ON UPDATE CASCADE
)
DROP TABLE Shifts
CREATE TABLE Shifts
(
Id INT PRIMARY KEY IDENTITY,
StartTime TIME,
EndTime TIME,
ShiftDescription NVARCHAR(20),
ProductionUnitId INT FOREIGN KEY REFERENCES ProductionUnits(Id) ON DELETE CASCADE ON UPDATE CASCADE
)
DROP TABLE ProductionRecords
CREATE TABLE ProductionRecords
(
Id INT PRIMARY KEY IDENTITY,
CreatedOn DATETIME,
CreatedBy NVARCHAR(50),
ModifiedOn DATETIME,
ModifiedBy NVARCHAR(50)
)
DROP TABLE dbo.Referencias
CREATE TABLE Referencias
(
Id INT PRIMARY KEY IDENTITY,
Name NVARCHAR(15),
)
DROP TABLE dbo.CheckListRecords
CREATE TABLE CheckListRecords
(
Id INT PRIMARY KEY IDENTITY,
Value NVARCHAR(3),
ReferenciaId INT FOREIGN KEY REFERENCES Referencias(Id) ON DELETE CASCADE ON UPDATE CASCADE,
ShiftId INT FOREIGN KEY REFERENCES Shifts(Id) ON DELETE CASCADE ON UPDATE CASCADE,
CheckListGroupItemId INT FOREIGN KEY REFERENCES dbo.CheckListGroupItems(Id) ON DELETE CASCADE ON UPDATE CASCADE,
ProductionRecordsId INT FOREIGN KEY REFERENCES ProductionRecords(Id) ON DELETE CASCADE ON UPDATE CASCADE
)
问题是当我添加
CheckListGroupItemId INT FOREIGN KEY REFERENCES dbo.CheckListGroupItems(Id) ON DELETE CASCADE ON UPDATE CASCADE,
但是我需要知道它属于哪个项目,但是如果我删除ON DELETE CASCADE的话,这个项目就可以了
在外键和处理级联路径方面,我对SQL不太熟悉-
在这种情况下我该怎么办?
答案 0 :(得分:2)
删除CheckListRecords
行时,有两种删除ProductionUnits
的路径。这就是它所抱怨的。
ProductionUnits ->
Cells ->
CheckLists ->
CheckListGroups ->
CheckListGroupItems ->
CheckListRecords
...和...
ProductionUnits ->
Shifts ->
CheckListRecords
笨蛋-你不能拥有...没有真正简单的方法可以解决它:-(
这很常见。但是,有希望-有一种合理的方法可以解决它...不太可怕。当您收到这样的消息时,请从其抓紧的表中退后一步……并且当您在删除路径中找到指向同一张表的多个ON DELETE CASCADE
列时,您便找到了罪魁祸首。
在我提出解决方案之前,请先观察以下几点:一方面,您已经获得了身份生成的ID。因此,On Update Cascade
可能不应该在这样的环境中指定,因为ID不会轻易更改(除非您在某处的行为非常糟糕)。
另一种最佳实践,请注意:创建表时指定架构:
CREATE TABLE dbo.ProductionUnits
(
-- etc.
)
在视图和过程中引用表时,...和总是使用该模式。
好的-那么如何处理冲突?您可能会考虑做的是从CheckListRecords
到Shifts
删除外键,而是在Shifts
上实施 delete触发器删除受影响的{{1} }行。很久以前...在声明性引用完整性之前,您必须处理使用触发器来管理关系。在这样的地方它仍然派上用场。
假设您已将架构添加到表声明中,则大致类似于:
CheckListRecords
看,还不错,是吗?
如果由于某种原因您只是必须更新create trigger [Shifts.Delete.Trigger] on dbo.Shifts for delete as
begin
set nocount on;
delete dbo.CheckListRecords where ShiftId in ( select Id from deleted );
end
,它会变得更加复杂。为了实现逻辑,您将不得不在Shifts.Id
表上有一个备用键……最好是您永远不会更新的列,或者至少一个在更改Shifts
时不会更新的列。也许是Id
列?如果您没有候选键,则可以添加一个StartTime
列。例如:
uniqueidentifier
您的大多数视图和逻辑都将完全忽略此列。您甚至不需要让EF看到它。按照我的声明方式,它会在插入时自动设置(类似于标识列)。
使用CREATE TABLE Shifts
(
Id INT PRIMARY KEY IDENTITY,
StartTime TIME,
EndTime TIME,
ShiftDescription NVARCHAR(20) ,
ProductionUnitId INT FOREIGN KEY REFERENCES ProductionUnits(Id) ON DELETE CASCADE ON UPDATE CASCADE,
RowId UNIQUEIDENTIFIER
CONSTRAINT [Shifts.RowId.Default] DEFAULT ( NEWID() )
CONSTRAINT [Shifts.RowId.Unique] UNIQUE
)
的唯一代码是更新触发器:
RowId
这不是超级恐怖...但并不理想。确实,如果您没有任何理由要更新ID列(并且您确实不应该),则可以跳过所有此更新触发器和多余的列废话。
我认为,如果您具有基于触发器的参照完整性,则必须将其告知EF ...但是EF不是我的员工的方式...因此我对此无能为力。但是我几乎可以肯定,当您向EF描述数据模型时,这是一个相当简单的声明。