替换Context_Info SQL Azure

时间:2012-07-30 13:45:06

标签: sql-server-2008 azure azure-sql-database context-info

我目前正在使用Master数据库的CONTEXT_INFO属性来存储登录的用户名,以便稍后在表触发器中使用它进行审核。

迁移到SQL Azure时,突然出现了跨数据库连接问题,我无法找到解决此问题的直接解决方案。

以下是问题详情:

  1. 我从数据访问层调用存储过程XXX并将用户名作为参数传递
  2. 用户名用于设置XXX
  3. 中的CONTEXT_INFO值
  4. 然后在表插入/更新/删除触发器中使用CONTEXT_INFO值来存储应用程序审核的用户名
  5. 到目前为止我找到的解决方案:

    1. 在数据库中创建表格以用作CONTEXT_INFO
    2. 在数据访问层中使用2个连接字符串,一个用于主数据库(用于设置CONTEXT_INFO),另一个用于应用程序,每次打开与应用程序的连接之前执行SET CONTEXT_INFO
    3. 但我发现这两种解决方案都存在风险,特别是在将来将数据库扩展到多个SQL Azure数据库时。

      感谢您的支持。

1 个答案:

答案 0 :(得分:4)

我采取的方法如下所示。诀窍是检查运行不在SQL Azure上运行,然后我们需要调用'SET CONTEXT_INFO ...'。这允许相同的代码在本地SQL Server Express和Azure上执行而无需更改。

  1. 创建一个表来存储上下文信息(不在master中但在同一个数据库中)

    CREATE TABLE [dbo].[ContextInfo] (
        [ContextInfo] varbinary(128) not null,
        [ApplicationUsername] nvarchar(128) not null,
        [UpdatedAt] datetime NOT NULL,
        CONSTRAINT [PK_UserContextInfo] PRIMARY KEY CLUSTERED ([ContextInfo] ASC)
    )
    
  2. 创建一个存储过程以设置从应用程序

    调用的“上下文信息”
    CREATE PROCEDURE [dbo].[SetContextInfo]
      @ApplicationUsername nvarchar(128)
    AS
    
    SET NOCOUNT ON
    
    -- Remove all context items older than an 5 minutes ago
    DELETE
      FROM [dbo].[ContextInfo]
     WHERE [UpdatedAt] < DATEADD(mi, -5, GETUTCDATE())
    
    --
    -- Use the MERGE command to do an update/insert
    -- See: http://technet.microsoft.com/en-us/library/bb510625.aspx
    --
    
    IF SERVERPROPERTY('edition') <> 'SQL Azure'
    BEGIN
        DECLARE @b varbinary(128)
        SET @b = CONVERT(varbinary(128),newid())
        EXEC sp_executesql @statement=N'SET CONTEXT_INFO @b',@params=N'@b varbinary(128)',@b=@b
    END
    
    DECLARE @ContextInfo varbinary(128)
    SELECT @ContextInfo = CONTEXT_INFO()
    
    MERGE [dbo].[ContextInfo] AS target
    USING (SELECT @ContextInfo, @ApplicationUsername) AS source ([ContextInfo], [ApplicationUsername])
       ON (target.[ContextInfo] = source.[ContextInfo])
     WHEN MATCHED THEN 
            UPDATE SET [ApplicationUsername] = source.[ApplicationUsername], [UpdatedAt] = GETUTCDATE()
     WHEN NOT MATCHED THEN  
            INSERT ([ContextInfo], [ApplicationUsername], [UpdatedAt])
            VALUES (source.[ContextInfo], source.[ApplicationUsername], GETUTCDATE());
    
  3. 创建存储过程以“获取上下文信息”

    CREATE PROCEDURE [dbo].[GetContextInfo]
    AS
        SET NOCOUNT ON
        DECLARE @ContextInfo varbinary(128)
        SELECT @ContextInfo = CONTEXT_INFO()
    
        SELECT [ApplicationUsername]
          FROM [dbo].[ContextInfo]
         WHERE [ContextInfo] = @ContextInfo
    GO
    
  4. 在触发源中,使用:

    DECLARE @UserContext TABLE ([Username] VARCHAR(128))
    INSERT INTO @UserContext (Username)
    EXEC [dbo].[GetContextInfo]
    
  5. 现在您将用户名存储在表变量中。如果管理员在您的应用程序之外应用更改,您可能还需要检查用户名是否未设置,并且默认为* SYSTEM_USER *。