0

我有一个存储过程如下:

CREATE PROCEDURE [ODataTaskResult_Create]
    @ODataTaskId BIGINT,
    @ODataTaskResultTypeId INTEGER,
    @Details CHARACTER VARYING(MAX)
AS
    BEGIN TRANSACTION
        INSERT INTO [ODataTaskResult] WITH (ROWLOCK, XLOCK) ([ODataTaskId], [ODataTaskResultTypeId], [Details], [CreatedOn])
        VALUES (@ODataTaskId, @ODataTaskResultTypeId, @Details, SYSDATETIMEOFFSET())

        DECLARE @ODataTaskResultTypeName CHARACTER VARYING(255)
        SET @ODataTaskResultTypeName = (
            SELECT TOP 1 [ODataTaskType].[Name] FROM [ODataTaskType]
            WHERE [ODataTaskType].[Id] = @ODataTaskResultTypeId)

        IF (@ODataTaskResultTypeName = 'Finish')
        BEGIN
            UPDATE [ODataTask]
            SET [ODataTask].[FinishedOn] = SYSDATETIMEOFFSET()
            WHERE [ODataTask].[Id] = @ODataTaskId
        END ELSE IF (@ODataTaskResultTypeName = 'Delete')
        BEGIN
            UPDATE [ODataTask]
            SET [ODataTask].[DeletedOn] = SYSDATETIMEOFFSET()
            WHERE [ODataTask].[Id] = @ODataTaskId
        END ELSE
            RAISERROR('Invalid result type', 16, 1)

    COMMIT TRANSACTION
GO

这个过程应该查看传入的@ODataTaskResultTypeId参数,从另一个表中拉出结果类型,并根据Name该记录中的列做一些事情。

基本上,当针对任务输入结果时,它定义了它是如何完成的。如果任务完成,我需要修改FinishedOn父任务记录上的列,而不是更改DeletedOn列。我们有一个约束表明FinishedOn并且DeletedOn可能不都是NOT NULL

在这一点上感觉,由于我已经将不同的案例逻辑硬编码到存储过程中,这使得可维护性变得困难并且阻止它正常工作,除非ODataTaskResult表具有正确的初始条目。

我是否应该使该ODataTaskResult_Create过程仅创建结果,然后调用另一个过程ODataTask_Finish以及另一个过程ODataTask_Delete

是否有解决这个问题的不同方法通常更容易维护?

我们从不硬删除条目,只有软删除。

4

1 回答 1

1

如果你想要一个灵活的解决方案,你可以在你的ODataTaskType表中添加一个列来保存存储过程以供以后运行。然后,您可以使用一些动态 sql 进行调度。如果该列称为PostComplete_Proc,请说:

create proc dbo.[ODataTaskResult_Create]
    @ODataTaskId bigint,
    @ODataTaskResultTypeId int,
    @Details varchar(max)
as

declare
    @proc sysname,
    @params nvarchar(max) = '@ODataTaskId bigint'

begin transaction
    insert into dbo.[ODataTaskResult] with (rowlock, xlock) (
        [ODataTaskId], [ODataTaskResultTypeId], [Details], [CreatedOn]
    ) values
        @ODataTaskId, 
        @ODataTaskResultTypeId, 
        @Details,
        sysdatetimeoffset()
    );

    select top 1 -- Would there really be more than 1? Why hide potential errors?
        @proc = PostComplete_Proc
    from
        dbo.[ODataTaskType]
    where
        Id = @ODataTaskResultTypeId;

    if @proc is null
        raiserror('Invalid result type', 16, 1);
    else
        exec @proc, @params, @ODataTaskId;

commit transaction;

然后创建相关的存储过程。如果您有许多结果类型和很少的过程,您甚至可以添加另一个级别,其中过程存储在单独的表中并通过外键引用。

我发现很难说服自己rowlock, xlock在这里做任何事情。

于 2013-11-11T20:16:54.663 回答