Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何知道TriggerContext当前更新的表?_C#_.net_Sql Server_Sqlclr - Fatal编程技术网

C# 如何知道TriggerContext当前更新的表?

C# 如何知道TriggerContext当前更新的表?,c#,.net,sql-server,sqlclr,C#,.net,Sql Server,Sqlclr,我有一个数据库,其中的数据必须有条件地复制到同一服务器上不同数量的数据库。接收表将具有相同的名称,但仅具有键列 我想将db浏览逻辑放在SQLCLR中,并在源表中的数据更新后立即做出反应。因此,我希望重用相同的复制方法,根据当前更新的表复制键值 internal static void ReplicateToInstances() { if (!IsTableWriteTriggerContextAvailable()) throw new InvalidOperationExceptio

我有一个数据库,其中的数据必须有条件地复制到同一服务器上不同数量的数据库。接收表将具有相同的名称,但仅具有键列

我想将db浏览逻辑放在SQLCLR中,并在源表中的数据更新后立即做出反应。因此,我希望重用相同的复制方法,根据当前更新的表复制键值

internal static void ReplicateToInstances()
{
    if (!IsTableWriteTriggerContextAvailable()) throw new InvalidOperationException();

    string currentlyUpdatedTable; // = SqlContext.TriggerContext.??????        

    // rest of the code, irrelevant to the current issue.
}
有没有办法知道当前TriggerContext实例位于哪个表上?

这应该是显而易见的,但不幸的是,事实并非如此。T-SQL触发器可以使用@PROCID,然后在sys.objects中查找父对象,但对SQLCLR来说就不是这样了。下面是一个Microsoft连接项目,建议修复此问题:

这里有一个关于重复问题的解决方法:

该解决方法(即使用上下文信息)的问题在于,如果以下任一条件为真,则该方法不起作用:

上下文信息已被用于其他目的

触发器可以更新具有SQLCLR触发器的表,该表需要知道其父对象的名称

但是,使用sp_settriggerorder程序将订单设置为第一位是正确的

我确实对此有一个解决方案,即使在嵌套的触发器场景中也可能有效,但我还没有时间测试它。请参阅下面的更新部分。不过,其概念是在INSERT、UPDATE、DELETE触发器中按照以下步骤进行操作,并将触发器顺序设置为First:

创建触发器[SchemaName]。[tr_SetTriggerInfo] 在[SchemaName].[TableName]上 插入、删除、更新后 像 开始 创建表TriggerInfo TriggerObjectID INT,TriggerName sysname, ParentObjectID INT、ParentName sysname、TriggerNestLevel INT; 在TriggerInfo中插入TriggerObjectID、TriggerName、, ParentObjectID、ParentName、TriggerNestLevel 选择@@PROCID, trggr.[name]作为[TriggerName], trggr.[parent\u object\u id]作为[ParentObjectID], 对象名称trggr。[parent\u OBJECT\u id]作为[ParentName], 触发器\u NESTLEVEL@@PROCID,'AFTER','DML'作为[TriggerNestLevel] 从sys.objects trggr 其中trggr.[object_id]=@@PROCID; 终止 去 EXEC sp_SetTriggerOrder@TriggerName=N'[SchemaName].[tr_SetTriggerInfo]', @顺序=N‘第一’, @StmtType=N'DELETE'; EXEC sp_SetTriggerOrder@TriggerName=N'[SchemaName].[tr_SetTriggerInfo]', @顺序=N‘第一’, @StmtType=N'INSERT'; EXEC sp_SetTriggerOrder@TriggerName=N'[SchemaName].[tr_SetTriggerInfo]', @顺序=N‘第一’, @StmtType=N'UPDATE'; 去 出于以下原因,这应该有效:

SQLCLR触发器,使用Context Connection=true的ConnectString;可以从本地临时表中读取

本地临时表在嵌套场景中的行为如下:

如果父上下文中已经存在临时表,那么DML语句将看到它并与之交互,并且这些更改将能够同时添加嵌套级别和父级别—这是一个非常方便的功能 如果父上下文中已经存在临时表,并且为相同的临时表名称执行CREATE table语句,而不是出错,则它将创建该表的新副本,并且父上下文中相同名称的临时表现在将不可访问,即隐藏。也就是说,如果您处于级别3,那么当该级别完成时,在级别2中运行的触发器代码仍将具有级别2值,而不是级别3值。 这在CONTEXT_INFO中是不可能的,这就是CONTEXT_INFO不适用于嵌套场景的原因:级别3将覆盖级别2的值,因此当控件返回到级别2时,它现在在CONTEXT_INFO中的值是错误的。假设我们只能将一个触发器设置为第一个,而不能控制哪一个是第二个,除非您的触发器不超过3个,在这种情况下,您也可以使用最后一个位置,那么您不能保证SQLCLR触发器将在第一个触发器之后立即触发,如果另一个触发器触发,修改了一个表,而该表上有此触发器设置,那么您就破坏了上下文信息中的数据

更新
实际上,上面的临时表解决方案可能不起作用,因为一旦t-SQL触发器结束,本地临时表可能会消失,这是在SQLCLR触发器触发之前。下周我还需要测试这个。如果这是实际行为,而本地临时工不起作用,那么我有另一个可行的想法。

@Crono如果您阅读了我在您认为我已经完成之后添加的所有内容,这不是个坏消息。我发布了一个解决方案,肯定会奏效。我已经计划下周在u
更新另一个问题。@Crono实际上,我的想法可能行不通。请参阅更新部分。