我目前正在使用Master数据库的CONTEXT_INFO属性来存储登录的用户名,以便稍后在表触发器中使用它进行审核。
迁移到SQL Azure时,突然出现了跨数据库连接问题,我无法找到解决此问题的直接解决方案。
以下是问题详情:
到目前为止我找到的解决方案:
但我发现这两种解决方案都存在风险,特别是在将来将数据库扩展到多个SQL Azure数据库时。
感谢您的支持。
答案 0 :(得分:4)
我采取的方法如下所示。诀窍是检查运行不在SQL Azure上运行,然后我们需要调用'SET CONTEXT_INFO ...'。这允许相同的代码在本地SQL Server Express和Azure上执行而无需更改。
创建一个表来存储上下文信息(不在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)
)
创建一个存储过程以设置从应用程序
调用的“上下文信息”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());
创建存储过程以“获取上下文信息”
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
在触发源中,使用:
DECLARE @UserContext TABLE ([Username] VARCHAR(128))
INSERT INTO @UserContext (Username)
EXEC [dbo].[GetContextInfo]
现在您将用户名存储在表变量中。如果管理员在您的应用程序之外应用更改,您可能还需要检查用户名是否未设置,并且默认为* SYSTEM_USER *。