存储过程调用之间的事务重叠

时间:2015-11-20 05:58:25

标签: stored-procedures transactions azure-sql-database

我在SQL Azure中遇到存储过程的问题,它负责在表上创建记录。当同一个存储过程被调用多次/或两次以上时,它就会失败。

ALTER PROCEDURE [dbo].[usp_ActiveTouchPoints]
-- Add the parameters for the stored procedure here
@pAppOrgSyncId uniqueidentifier,
@pTouchPointId uniqueidentifier = null,
@pDoActive bit = 1,
@pRetValue BIT OUTPUT
AS BEGIN

SET NOCOUNT ON;

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
--SET XACT_ABORT OFF

DECLARE @TransactionName varchar(20) = substring(CONVERT(NVARCHAR(50), NEWID()), 25,12);

BEGIN TRANSACTION @TransactionName
-- 2.  Copy Attribute mappings
BEGIN TRY

DECLARE @vTaskIds Table(TaskId uniqueidentifier)

DECLARE @vCreatedTasks VARCHAR(MAX)

print 'usp_ActiveInitialTouchPoints for OrgAPPSYNCID : ' + CAST(@pAppOrgSyncId as VARCHAR(100))

Exec usp_ActiveInitialTouchPoints @pAppOrgSyncId = @pAppOrgSyncId, 
            @pTouchPointId = @pTouchPointId, 
            @pDoActive = @pDoActive,
            @pTaskIds = @vCreatedTasks OUTPUT

DECLARE @vReverseOrgAppSyncId uniqueidentifier
DECLARE @vOrgId uniqueidentifier
DECLARE @vTemplateId uniqueidentifier
DECLARE @vRevTemplateId uniqueidentifier

SELECT @vTemplateId = TemplateId 
    From OrgAppSync
where OrgAppSyncId = @pAppOrgSyncId


SELECT @vReverseOrgAppSyncId = ReverseOrgAppSyncId,
       @vOrgId = OrgId,
       @vRevTemplateId = TemplateId
    From OrgAppSync 
where OrgAppSyncId = @pAppOrgSyncId

DECLARE @vRevCreatedTasks VARCHAR(MAX)

    print 'usp_ActiveInitialTouchPoints for OrgAPPSYNCID : ' + CAST(@vReverseOrgAppSyncId as VARCHAR(100))

Exec usp_ActiveInitialTouchPoints @pAppOrgSyncId = @vReverseOrgAppSyncId, 
            @pTouchPointId = @pTouchPointId, 
            @pDoActive = @pDoActive,
            @pTaskIds = @vRevCreatedTasks OUTPUT 

--INSERT INTO @vTaskIds 
--  Select * from FN_STRINGTOTABLE(@vCreatedTasks, ',')

--INSERT INTO @vTaskIds 
--  Select * from FN_STRINGTOTABLE(@vRevCreatedTasks, ',')

Insert into @vTaskIds 
    SELECT TaskId from Task
    Where OrgAppSyncId in (@pAppOrgSyncId, @vReverseOrgAppSyncId)

DECLARE @vTaskId uniqueidentifier
DECLARE @vParentTaskId uniqueidentifier
DECLARE @vTouchpointId uniqueidentifier
DECLARE @vTouchpointDependencyId uniqueidentifier
DECLARE @vEventId INT
DECLARE @vOrdering INT
DECLARE @vFlag INT

print 'usp_ActiveTouchPoints - CTD'

-- Create Dependent Task before creating the TaskDependencies
IF @pTouchpointId IS NOT NULL
BEGIN

    DECLARE @vReturnVal BIT
    Declare @vDTouchpointId uniqueidentifier
    Declare @vOrgAppSyncId uniqueidentifier

    DECLARE TPD CURSOR LOCAL
    FOR
        SELECT TouchpointId from TouchpointDependency
        where ParentTouchpointId =  @pTouchpointId
    OPEN TPD
    FETCH NEXT FROM TPD into @vDTouchpointId

    WHILE @@Fetch_status = 0
    BEGIN

        Select @vOrgAppSyncId = OrgAppSync.OrgAppSyncId 
        from 
            Touchpoint
        Inner join Template 
                    on Touchpoint.TemplateId = Template.Templateid
        Inner join OrgAppSync 
                    on OrgAppSync.TemplateId = Template.TemplateId
        where 
                OrgAppSync.OrgAppSyncId in (@pAppOrgSyncId, @vReverseOrgAppSyncId)
        And     Touchpoint.TouchpointId = @vDTouchpointId

        Exec [dbo].[usp_ActiveTouchPoints] @pAppOrgSyncId = @vOrgAppSyncId, @pTouchPointId = @vDTouchpointId, @pDoActive = @pDoActive, @pRetValue = @vReturnVal OUTPUT

        FETCH NEXT FROM TPD into @vDTouchpointId
    END

    CLOSE TPD;
    DEALLOCATE TPD;
END

DECLARE CTD CURSOR LOCAL
FOR
    SELECT TouchpointDependency.ParentTouchpointId
        , TouchpointDependency.TouchpointDependencyId
        , TouchpointDependency.EventId
        , TouchpointDependency.Ordering 
        , Task.TaskId
        , IsNull(TouchpointDependency.Flag, 0) from Task
    Inner join TouchpointDependency on Task.TouchpointId = TouchpointDependency.ParentTouchpointId 
    AND IsNull(TouchpointDependency.Active, 1) = 1
    where Task.TaskId in (select TaskId from @vTaskIds)


OPEN CTD
FETCH NEXT FROM CTD into @vTouchpointId, @vTouchpointDependencyId, @vEventId, @vOrdering, @vParentTaskId, @vFlag

WHILE @@Fetch_status = 0
BEGIN

    IF NOT EXISTS(SELECT * FROM TASKDEPENDENCY where TouchpointDependencyId = @vTouchpointDependencyId
                    And ParentTaskId = @vParentTaskId)
    BEGIN
    print 'usp_ActiveTouchPoints - TDD'
        Insert into TaskDependency
        (
            TaskDependencyId,
            ParentTaskId,
            TouchpointDependencyId,
            TaskId, 
            EventId, 
            Ordering,
            ACTIVE,
            Flag
        )
        SELECT  NEWID()
                , @vParentTaskId
                , @vTouchpointDependencyId
                , TaskId
                , @vEventId
                , @vOrdering
                , 1
                , @vFlag
        From Task 
        Inner join TouchpointDependency 
            on Task.TouchpointId = TouchpointDependency.TouchpointId 
        where TouchpointDependency.TouchpointDependencyId = @vTouchpointDependencyId
        AND Task.TaskId in (select TaskId from @vTaskIds)

    END

    FETCH NEXT FROM CTD into @vTouchpointId, @vTouchpointDependencyId, @vEventId, @vOrdering, @vParentTaskId, @vFlag
END
CLOSE CTD;
DEALLOCATE CTD;

    IF XACT_STATE() = 1
    BEGIN
        COMMIT TRANSACTION @TransactionName
    END

    SET @pRetValue = 1
END TRY

BEGIN CATCH 
    IF XACT_STATE() <> 0
    BEGIN
        ROLLBACK TRANSACTION @TransactionName
    END

    INSERT INTO ERRORLOG
    SELECT  
            ERROR_NUMBER(),
            ERROR_MESSAGE(),
            ERROR_SEVERITY(),
            ERROR_STATE(),
            ERROR_LINE(),
            ERROR_PROCEDURE(),
            NEWID()


    SELECT 
        ERROR_NUMBER() AS ErrorNumber
        ,ERROR_MESSAGE() AS ErrorMessage;


    SET @pRetValue = 0

END CATCH

END

存储过程中发生了大量插入操作。一些插入/更新。它还会打开一个Cursor,但我将其标记为本地范围光标。

现在使用Entity Framework调用此存储过程,并且网站使用WebAPI调用它。

现在的问题是,当我多次调用同一个存储过程时,它说:

  

“无法回滚76C80318BB6A。没有事务或保存点   名字被发现“

但是当我打电话给它并等到我完成然后再打电话时,同样的工作正常。我不知道要解决这个问题。您认为代码存在问题吗?

1 个答案:

答案 0 :(得分:1)

在调用初始存储过程时确保SET IMPLICIT_TRASACTIONS为OFF,否则请记住存储过程调用中具有未完成事务的代码。