我正在将数据库优先方法与EF核心配合使用,并试图找出解决以下问题的干净方法-
请考虑下面的学生出勤表(已删除不相关的列),该表存储上课日期,并允许学生输入他的课程评分-
create table Student (
Id int Identity(1, 1) not null,
ClassDate smalldatetime not null,
ClassRatingByStudent varchar(250) not null
)
这是一个Web应用程序,在该应用程序中,学校出勤系统会自动在EOD处填充上表,然后要求学生(比如几天后)添加课程评分。当表由学校出勤系统填充时,ClassRatingByStudent列中没有任何内容。然后,当学生登录时,他必须添加评分。
如您所见,当学校出勤系统填充表格时,ClassRatingByStudent必须为null;而当学生保存其更改时,ClassRatingByStudent必须为非null。一种明显的解决方案是使ClassRatingByStudent列可为空,并在代码中处理它,但是我想知道是否存在更整洁的数据库(或EF)级别的解决方案,或者针对此类情况的某种模式/体系结构准则?
答案 0 :(得分:4)
我不知道,但也许CHECK
约束可以帮助您:
CREATE TABLE TestTable(
ID int NOT NULL IDENTITY,
RatingAllowed bit NOT NULL DEFAULT 0, -- switcher
RatingValue varchar(250),
CONSTRAINT PK_TestTable PRIMARY KEY(ID),
CONSTRAINT CK_TestTable_RatingValue CHECK( -- constraint
CASE
WHEN RatingAllowed=0 AND RatingValue IS NULL THEN 1
WHEN RatingAllowed=1 AND RatingValue IS NOT NULL THEN 1
ELSE 0
END=1
)
)
INSERT TestTable(RatingAllowed,RatingValue)VALUES(0,NULL)
INSERT TestTable(RatingAllowed,RatingValue)VALUES(1,'AAA')
-- The INSERT statement conflicted with the CHECK constraint "CK_TestTable_RatingValue"
INSERT TestTable(RatingAllowed,RatingValue)VALUES(0,'AAA')
INSERT TestTable(RatingAllowed,RatingValue)VALUES(1,NULL)
答案 1 :(得分:1)
我找到了一种变型,如何使用另一个表作为切换器进行检查
CREATE TABLE TableA(
ID int NOT NULL IDENTITY PRIMARY KEY,
StudentID int NOT NULL,
Grade int
)
CREATE TABLE TableB(
StudentID int NOT NULL PRIMARY KEY
)
GO
-- auxiliary function
CREATE FUNCTION GradeIsAllowed(@StudentID int)
RETURNS bit
BEGIN
DECLARE @Result bit=CASE WHEN EXISTS(SELECT * FROM TableB WHERE StudentID=@StudentID) THEN 1 ELSE 0 END
RETURN @Result
END
GO
-- constraint to check
ALTER TABLE TableA ADD CONSTRAINT CK_TableA_Grade CHECK(
CASE dbo.GradeIsAllowed(StudentID) -- then we can use the function here
WHEN 1 THEN CASE WHEN Grade IS NOT NULL THEN 1 ELSE 0 END
WHEN 0 THEN CASE WHEN Grade IS NULL THEN 1 ELSE 0 END
END=1)
GO
-- Tests
INSERT TableB(StudentID)VALUES(2) -- allowed student
INSERT TableA(StudentID,Grade)VALUES(1,NULL) -- OK
INSERT TableA(StudentID,Grade)VALUES(2,5) -- OK
INSERT TableA(StudentID,Grade)VALUES(1,4) -- Error
INSERT TableA(StudentID,Grade)VALUES(2,NULL) -- Error
INSERT TableB(StudentID)VALUES(1) -- add 1
UPDATE TableA SET Grade=4 WHERE StudentID=1 -- OK
UPDATE TableA SET Grade=NULL WHERE StudentID=1 -- Error