C# SQL Server触发器-如果列IsLocked位为true,则防止行更新

C# SQL Server触发器-如果列IsLocked位为true,则防止行更新,c#,sql-server,asp.net-mvc,sql-server-2016,database-trigger,C#,Sql Server,Asp.net Mvc,Sql Server 2016,Database Trigger,通过ASP.NET 4.6.2 MVC web应用程序访问SQL Server 2016 我有表“Building”,一个建筑可以有多个“Components”。例如,Building1有组件1和组件2。。。等 有人要求我能锁上一栋大楼。锁定意味着不能再修改组件(创建/更新/删除)。可以想象,这是一个巨大的应用程序,一个组件可以在100多个地方修改。甚至没有人能回答这个问题:“我需要锁在哪里?” 我的想法是锁定我能想到的任何地方,然后作为一个安全网,创建一个SQL触发器,如果组件表“IsLock

通过ASP.NET 4.6.2 MVC web应用程序访问SQL Server 2016

我有表“Building”,一个建筑可以有多个“Components”。例如,Building1有组件1和组件2。。。等

有人要求我能锁上一栋大楼。锁定意味着不能再修改组件(创建/更新/删除)。可以想象,这是一个巨大的应用程序,一个组件可以在100多个地方修改。甚至没有人能回答这个问题:“我需要锁在哪里?”

我的想法是锁定我能想到的任何地方,然后作为一个安全网,创建一个SQL触发器,如果组件表“IsLocked BIT”上的列为true,它将阻止所有修改。目前,我知道组件是否被锁定的唯一方法是IsLocked列是否等于true

所以,我说所有这些都是为了这个。如果要修改的行的列IsLocked=1,如何创建SQL Server触发器来防止数据行被修改

编辑1 在我看来,这不是复制品。使用代替删除或代替。。。这对我不起作用。如果我做这个而不是。。。然后在这里面,我需要提供提交逻辑。我不想提供提交逻辑。我只想在插入、更新、删除之前运行检查

编辑2-代替更新/删除是最佳选择
如果不是。。。是我的最佳选择,而不是使用更新/删除来重写我所拥有的吗?我不知道怎么做。请记住,请求将来自web应用程序。我不知道他们是在更新一列还是整个实体,或者他们将传递什么。我知道,按照我的编写方式,它将捕获任何插入/更新/删除,并在锁定时阻止它。如果有更好的方法,请写下来并解释为什么更好。

以下是我提出的解决方案:

    ALTER TRIGGER [dbo].[PreventLockedModification]
ON [dbo].[Component]
FOR INSERT, UPDATE, DELETE
AS 
BEGIN

    SET NOCOUNT ON;

    --DETERMINE INSERT(I) UPDATE(U) OR DELETE(D)
----------------------------------------------------------------------------------------------------
  DECLARE @action as char(1);

    SET @action = 'I'; -- Set Action to Insert by default.
    IF EXISTS(SELECT * FROM DELETED)
    BEGIN
        SET @action = 
            CASE
                WHEN EXISTS(SELECT * FROM INSERTED) THEN 'U' -- Set Action to Updated.
                ELSE 'D' -- Set Action to Deleted.       
            END
    END
----------------------------------------------------------------------------------------------------

    DECLARE @ErrorMsg nvarchar(100) = 'This row is locked and cannot be updated';
    DECLARE @IsLocked bit;
    DECLARE @BuildingId bigint;
    DECLARE @UnitId bigint;
    DECLARE @IsComplete_Building bit;
    DECLARE @IsComplete_Unit bit;

----------------------------------------------------------------------------------------------------
    IF @action = 'U' or @action = 'D'
        BEGIN
            SELECT @IsLocked = IsLocked FROM deleted;
            IF @IsLocked = 1
                BEGIN
                    RAISERROR (@ErrorMsg, 16, 1);
                    ROLLBACK TRANSACTION
                END
        END
----------------------------------------------------------------------------------------------------
    ELSE IF @action = 'I'
        BEGIN
            SELECT @BuildingId = BuildingId FROM inserted;
            SELECT @UnitId = UnitId FROM inserted;

            SELECT @IsComplete_Building = IsComplete FROM Building WHERE BuildingId = @BuildingId
            SELECT @IsComplete_Unit = IsComplete FROM Unit WHERE UnitId = @UnitId

            IF @IsComplete_Building = 1 or @IsComplete_Unit = 1
                BEGIN
                    RAISERROR (@ErrorMsg, 16, 1);
                    ROLLBACK TRANSACTION
                END
        END
----------------------------------------------------------------------------------------------------



END

而不是delete
触发器。这几乎肯定是一个重复的问题。可能重复而不是更新/删除是您最好的选择。当然,您必须在触发器中编写update或delete语句,但它不应该比您现在的代码长太多。