Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 防止循环和多个级联路径_Sql_Sql Server_Entity Framework - Fatal编程技术网

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

我有以下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 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,对不起,我不太理解你关于时间戳的建议。你能提供一个代码示例吗。这很容易理解。非常感谢。