我有一个雇佣表的表结构:
hireId int primary key
carId int not null foreign key
onHireDate datetime not null
offHireDate datetime not null
我正在尝试对多用户系统进行编程,该系统不允许汽车重叠时间段和非工作时段。我需要能够以非连续顺序添加招聘。还需要允许编辑招聘。
任何限制表格或使用触发器等以防止重叠的方法?我正在使用实体框架,所以我想要正常插入表,然后如果失败则抛出一些可捕获的异常等。
答案 0 :(得分:3)
CREATE TRIGGER tri_check_date_overlap ON your_table
INSTEAD OF INSERT
AS
BEGIN
IF @@ROWCOUNT = 0
RETURN
-- check for overlaps in table 'INSERTED'
IF EXISTS(
SELECT hireId FROM your_table WHERE
(INSERTED.onHireDate BETWEEN onHireDate AND offHireDate) OR
(INSERTED.offHireDate BETWEEN onHireDate AND offHireDate)
)
BEGIN
-- exception? or do nothing?
END
ELSE
BEGIN
END
END
GO
答案 1 :(得分:3)
考虑这个问题:
SELECT *
FROM Hire AS H1, Hire AS H2
WHERE H1.carId = H2.carId
AND H1.hireId < H2.hireId
AND
CASE
WHEN H1.onHireDate > H2.onHireDate THEN H1.onHireDate
ELSE H2.onHireDate END
<
CASE
WHEN H1.offHireDate > H2.offHireDate THEN H2.offHireDate
ELSE H1.offHireDate END
如果所有行都符合您的业务规则,则此查询将为空集(假设为closed-open representation of periods,即结束日期是该时段内未考虑的最早时间粒度。)
由于SQL Server does not support subqueries within CHECK
constraints,将相同的逻辑放在触发器中(但不是INSTEAD OF
触发器,除非您可以为解决重叠提供逻辑)。
使用Fowler的替代查询:
SELECT *
FROM Hire AS H1, Hire AS H2
WHERE H1.carId = H2.carId
AND H1.hireId < H2.hireId
AND H1.onHireDate < H2.offHireDate
AND H2.onHireDate < H1.offHireDate;
答案 2 :(得分:0)
我现在正在使用域驱动设计技术。这使我不必担心数据库触发器等,并将所有逻辑保留在.Net代码中。答案在这里,以便人们可以看到替代方案。
我将句点集合的父级视为aggregate root,并且根目录有时间戳。聚合根是事务,分发和并发的一致性边界(参见Evans - what I've learned since the blue book)。这用于检查上次向数据库确认任何更改的时间。
然后,我有方法将雇用期间添加到父级。我在将运动添加到聚合根时测试重叠。例如AddHire(start,end)
- 将验证这在内存域对象中不会产生重叠。
AS没有重叠我保存更改(通过我的存储库),并检查数据库时间戳仍然与进程开始时相同。假设时间戳与检索实体时的时间戳相同,则更改将保持不变,数据库将更新时间戳。
如果其他人尝试在处理聚合根时保存更改,那么我将首先提交或者他们将提交。如果我先提交,则时间戳将不匹配,重叠检查将重新运行,以确保它们在中间时间内没有创建重叠。