在CLR触发器中访问.NET应用程序变量

在CLR触发器中访问.NET应用程序变量,.net,sql-server,sqlclr,audit,database-trigger,.net,Sql Server,Sqlclr,Audit,Database Trigger,我在C.NET中创建了一个小应用程序,我在其中初始化并分配了一些公共变量/静态变量,例如我的登录用户ID。现在,在这个应用程序中发生了一些数据库操作。我已经在一个单独的project.dll中创建了CLR触发器,它记录了登录用户所做的数据库更改,该位工作正常。现在,我需要在该数据库上执行操作的用户ID,并希望将其存储在我正在运行的应用程序中的公共变量中 有没有办法访问CLR触发器类中的.NET应用程序变量 有没有办法访问CLR触发器类中的.NET应用程序变量 否。也没有任何方法可以访问常规T-S

我在C.NET中创建了一个小应用程序,我在其中初始化并分配了一些公共变量/静态变量,例如我的登录用户ID。现在,在这个应用程序中发生了一些数据库操作。我已经在一个单独的project.dll中创建了CLR触发器,它记录了登录用户所做的数据库更改,该位工作正常。现在,我需要在该数据库上执行操作的用户ID,并希望将其存储在我正在运行的应用程序中的公共变量中

有没有办法访问CLR触发器类中的.NET应用程序变量

有没有办法访问CLR触发器类中的.NET应用程序变量

否。也没有任何方法可以访问常规T-SQL存储过程/函数/触发器之间的局部变量。如果要将信息从应用程序层传递到触发器,可以使用与T-SQL存储过程/特殊查询相同的选项:

将值存储在会话via中,该会话via是VARBINARY128数据类型。您可以通过上下文信息函数读取该值。该值在sys.dm_exec_sessions DMV中也是可读的。如果进程未设置该值,则该值将为NULL。如果您已经在使用上下文信息存储其他信息,则此方法不起作用

创建一个键控到每个会话id/SPID的本地临时表,并将值存储在其中。然后在每个触发器中从中选择。如果某个进程没有创建本地临时表,则SELECT查询将出现错误,因此可能需要将其包装在If对象_IDN'tempdb..tentableName'不是NULL构造中

如果使用SQL Server 2016或更新版本,则可以使用新的哈希表

在这三种情况下,在应用层中打开SqlConnection后,通过ExecuteOnQuery执行SQL语句来执行上述操作,然后执行其他操作。然后,在SQLCLR触发器中,第一步是使用Context Connection=true连接到当前进程/会话;抓住价值

此外,上面提到的所有三种方法都允许T-SQL代码也将此审计信息传递给触发器,无论它们是T-SQL还是SQLCLR。这一点很重要,因为应用程序是否会对发生的100%的更改负责是值得怀疑的。通常情况下,人们有SQL代理作业和/或临时支持/发布查询,如果需要在应用层中分配变量,则无法跟踪所做的更改

我在CLR触发器类静态变量(例如_userid)中分配了一个值,但在调用同一类中由我从触发器调用的另一个静态方法时,该值没有得到。为什么?若MSSQL服务器进程调用并评估CLR类,那个么我的应用程序也可以评估同一类

SQL Server不仅是与您的应用程序使用的应用程序域不同的应用程序域,而且是完全不同的CLR主机


无论哪种方式,您都不希望静态变量工作,因为所有SQL Server会话都将共享一个静态变量,因此会覆盖同时运行的其他会话;-

我想你做不到。您需要将UserId列添加到您监视的表中,这样触发器才能知道是哪个用户执行了此操作。@Andrey,我可以这样做,但为此,我必须在所有必要的表中添加列。如果我在CLR触发器类中声明静态变量(例如_userid)并从应用程序中为其赋值,会发生什么?它是否保留并可用于触发器?或者sql server每次调用CLR类时都会创建新的CLR类实例。如果您想对用户修改表的事实采取行动,最好将其记录下来。假设您的CLR触发器失败,或者您决定追溯应用它—您将不可避免地丢失编辑表的重要信息。您不能通过静态变量在应用程序和触发器之间传递内容,因为它们位于不同的进程中。应用程序是应用程序,触发器位于MSSQL服务器进程中。@Andrey,我完全同意您的看法。但我的要求没有什么不同。我想记录用户所做的每一次更改。与SQLServer本身提供的CDC类似。通过上述逻辑,这可能是不可能的。如果您想记录某些表的更改历史-通常的做法是在表本身中记录用户id和更改时间(如EditorID和Version),然后使用触发器填充您已经完成的历史表。