Sql 防止循环和多个级联路径
我有以下SQL表:Sql 防止循环和多个级联路径,sql,sql-server,entity-framework,Sql,Sql Server,Entity Framework,我有以下SQL表: create table dbo.Companies ( Id int identity not null constraint primary key clustered (Id), ); create table dbo.Workers ( Id int identity not null constraint primary key clustered (Id), CompanyId int not null, ); create table
create table dbo.Companies (
Id int identity not null constraint primary key clustered (Id),
);
create table dbo.Workers (
Id int identity not null constraint primary key clustered (Id),
CompanyId int not null,
);
create table dbo.Evaluations (
Id int identity not null constraint primary key clustered (Id),
CompanyId int not null,
WorkerId int not null
)
以及以下限制:
alter table dbo.Workers
add constraint FK_Workers_CompanyId foreign key (CompanyId) references dbo.Companies(Id) on delete cascade on update cascade;
alter table dbo.Evaluations
add constraint FK_Evaluations_CompanyId foreign key (CompanyId) references dbo.Companies(Id) on delete cascade on update cascade,
constraint FK_Evaluations_WorkerId foreign key (WorkerId) references dbo.Workers(Id) on delete no action on update no action;
我正在使用实体框架,当我尝试插入一条记录时,我得到了错误:
Additional information: Introducing FOREIGN KEY constraint 'FK_dbo.Workers_dbo.Companies_CompanyId' on table 'Workers' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
我应该更改约束还是应该更改数据库设计
让我解释一下为什么我要这样设计我的数据库:
1-工人表中的公司ID表示工人当前工作的公司
2-评估中的公司ID表示进行评估时工人的工作地点。。。WorkerId显然表示被评估的工人
对我来说,这一切都是有道理的,但也许我错了……更明确地说:
CREATE TABLE dbo.EventTypes (
EID INT PRIMARY KEY IDENTITY(1,1)
, EventDescription VARCHAR(40)
);
INSERT INTO dbo.EventTypes (EventDescription) VALUES ('Hired');
INSERT INTO dbo.EventTypes (EventDescription) VALUES ('Evaluated');
将使用这些数据并进行评估,以确定发生了什么,时间如下
CREATE TABLE dbo.Companies (
CID INT PRIMARY KEY IDENTITY(1,1)
/* ... */
);
CREATE TABLE dbo.Workers (
WID INT PRIMARY KEY IDENTITY(1,1)
/* ... */
);
CREATE TABLE dbo.History (
HistID INT PRIMARY KEY IDENTITY(1,1)
, TS DATETIME NOT NULL DEFAULT GETDATE()
, CompanyID INT NOT NULL FOREIGN KEY REFERENCES dbo.Companies(CID) ON UPDATE CASCADE ON DELETE CASCADE
, WorkerID INT NOT NULL FOREIGN KEY REFERENCES dbo.Workers(WID) ON UPDATE CASCADE ON DELETE CASCADE
, EventTypeID INT NOT NULL FOREIGN KEY REFERENCES dbo.EventTypes(EID) ON UPDATE CASCADE ON DELETE CASCADE
/* ...other generic history-traits... */
);
CREATE NONCLUSTERED INDEX Idx_History_TS ON dbo.History (TS) INCLUDE (CompanyID, WorkerID, EventTypeID) WITH (FILLFACTOR = 90);
CREATE NONCLUSTERED INDEX Idx_History_CompanyID ON dbo.History (CompanyID) WITH (FILLFACTOR = 90);
CREATE NONCLUSTERED INDEX Idx_History_WorkerID ON dbo.History (WorkerID) WITH (FILLFACTOR = 90);
CREATE NONCLUSTERED INDEX Idx_History_EventTypeID ON dbo.History (EventTypeID) WITH (FILLFACTOR = 90);
这将包含一系列事件,您可以根据自己的喜好对这些事件进行分类。例如,当关联的EventDescription='Evaluated'时,您的代码可以在此处查看:
CREATE TABLE dbo.Evaluations (
EvalID INT NOT NULL PRIMARY KEY FOREIGN KEY REFERENCES dbo.History(HistID) ON UPDATE CASCADE ON DELETE CASCADE
/* ...Eval columns... */
);
CREATE TABLE dbo.EvaluationItems (
ID INT PRIMARY KEY IDENTITY(1,1)
, EvalID INT NOT NULL FOREIGN KEY REFERENCES dbo.Evaluations (EvalID)
/* ...item details... */
);
GO
这只是作为一个模型提供的,评估项目不必如此
其次,最近的雇主:
CREATE VIEW dbo.WorkersLastEmployer AS
SELECT W.*, C.*
FROM dbo.Workers W
INNER JOIN (
SELECT H.HistID, H.TS, H.CompanyID, H.WorkerID, MAX(TS)OVER(PARTITION BY H.WorkerID) AS LastHired
FROM dbo.History H
INNER JOIN dbo.EventTypes E ON E.EID = H.EventTypeID
WHERE E.EventDescription = 'Hired'
) Hi ON Hi.WorkerID = W.WID
AND Hi.TS = Hi.LastHired
INNER JOIN dbo.Companies C on C.CID = Hi.CompanyID
GO
由于CompanyID已迁移到历史记录中,并且评估现在是一个直接子类,因此,公司Y的工人X评估视图:
CREATE VIEW dbo.WorkerEvalutations AS
SELECT E.*, W.*, C.*
FROM dbo.Evaluations E
INNER JOIN dbo.History H on E.EvalID = H.HistID
INNER JOIN dbo.Workers W on W.WID = H.WorkerID
INNER JOIN dbo.Companies C on C.CID = H.CompanyID
GO
此结构运行时没有警告,并将为您提供一个更易于扩展的框架。您的级联设置有两条通向dbo.companys的dbo.Evalutations的路径。我是否可以建议一种将员工与公司关系分离的设计,而是将这些关系建立在时间戳表中,并将评估作为同一时间戳表的子类,以便可以为评估或在新公司工作评估“EventType”列,在任何给定的评估期间,工作人员在哪里工作的视图是评估之前的第一个“更改”记录,按时间戳降序排列。CompanyID应该作为FK出现在时间戳表中。@JaazCole,对不起,我不太理解你关于时间戳的建议。你能提供一个代码示例吗。这很容易理解。非常感谢。