我们公司对每个相关数据库表执行基于触发器的审计日志记录,以便在每次更改数据时跟踪应用程序用户的更改。 这背后的概念很简单。比方说,我们有一个我们想要历史记录的简单表格,如下所示:
CREATE TABLE Product
(
ProductId INT Identity(1,1) NOT NULL,
Name VARCHAR(32) NOT NULL,
CONSTRAINT pk__product PRIMARY KEY (ProductId)
);
首先,我们创建第二个表,其中包含将应用于上表的每个写操作的完整历史记录:
CREATE TABLE Product__Hist
(
Revision INT NOT NULL,--Starts at 1. Will be incremented on every update.
IsRecordDeleted BIT NOT NULL,--Indicates whether the record still exists or has been deleted
[User] VARCHAR(8) NOT NULL,--Identifies the user that did the change
[Timestamp] DATETIME NOT NULL,--Timestamp of the user-activity
ProductId INT NOT NULL,
Name VARCHAR(32) NOT NULL,
CONSTRAINT pk__product__hist PRIMARY KEY CLUSTERED (ProductId ASC, Revision DESC)
);
最后但并非最不重要的是,我们需要«Product»表上的触发器,它将在需要时将数据写入历史表。触发器将在任何类型的数据修改上调用,例如插入,更新和删除:
CREATE TRIGGER tr__product__a__iud ON Product
AFTER INSERT, UPDATE, DELETE
AS
DECLARE
@productid INT,
@revision INT,
@user VARCHAR(8),
@name VARCHAR (32)
DECLARE
@usercontext TABLE (Usr VARCHAR(8))
BEGIN
INSERT INTO @usercontext (Usr)
EXEC dbo.GetContextInfo
SELECT @user = Usr FROM @usercontext--Retrieves user's identity
IF EXISTS(SELECT * FROM INSERTED)--INSERT OR UPDATE
BEGIN
DECLARE crs CURSOR FOR
SELECT ProductId, Name FROM inserted;
OPEN crs
FETCH NEXT FROM crs INTO @productid, @name
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @revision = COALESCE((SELECT Max(Revision) FROM Product__Hist WHERE ProductId = @productid),0)+1
INSERT INTO Product__Hist(ProductId, Revision, IsRecordDeleted, [User], Name) VALUES (@productid, @revision, 0, @user, @name)
FETCH NEXT FROM crs INTO @productid, @name
END
CLOSE crs
DEALLOCATE crs
END
ELSE IF EXISTS(SELECT * FROM DELETED)--DELETE
BEGIN
DECLARE crs CURSOR FOR
SELECT ProductId, Name FROM deleted;
OPEN crs
FETCH NEXT FROM crs INTO @productid, @name
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @revision = COALESCE((SELECT Max(Revision) FROM Product__Hist WHERE ProductId = @productid),0)+1
INSERT INTO Product__Hist(ProductId, Revision, IsRecordDeleted, [User], Name) VALUES (@productid, @revision, 1, @user, @name)
FETCH NEXT FROM crs INTO @productid, @name
END
CLOSE crs
DEALLOCATE crs
END
END
现在出现问题:大多数情况下,这个解决方案完全正常。但是,我不得不体验到,当触发器被调用时,实体框架有时会出现以下异常:«触发器返回结果集和/或运行时SET NOCOUNT OFF而另一个未完成的结果集处于活动状态»。可悲的是,我无法找出这种行为的根本原因。 以下是一些可能有用的额外输入以及我迄今为止尝试过的内容:
此版本的SQL Server不支持语句'CONFIG'。
我们非常感谢任何可以帮助我解决这个奇怪问题的信息。提前谢谢!
我知道关于同一个例外的其他问题很少。但是,由于我没有找到任何对我有帮助的东西,所以我决定去寻找一个新问题。