首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >访问SQLCLR触发器中的触发/父表名称

访问SQLCLR触发器中的触发/父表名称
EN

Stack Overflow用户
提问于 2020-02-04 15:10:23
回答 1查看 351关注 0票数 2

我正在C#中创建一个相对简单的SQL。

此CLR的工作是将事件发布到Azure事件网格主题。

我希望能够从任意多个表的触发器中调用这个特定的CLR (实际上很少)。

给定下面的核心代码,如何准确地检索导致/触发触发器的表的名称?我一点也不知道从哪里开始。

我希望能够删除SqlTrigger属性,并以某种方式访问var table属性的表名。

代码语言:javascript
复制
// I Would like to leave the attribute commented out
//
//[Microsoft.SqlServer.Server.SqlTrigger(Name = "PublishToEventGridTrigger",
//     Target = "NamesOfThings", Event = "FOR UPDATE, INSERT, DELETE")]
public static void PublishToEventGridTrigger()
{
    // TODO - How should these settings be handled?     
    //        Not sure if config files are accessible... To test..
    // ***************************************************************

    string topicHost = "https://####.eventgrid.azure.net/api/events";
    string topicKey = "####";

    // TODO - Get Table name for this
    var table = "How Do I set This";
    string eventType = $"##.{table}.{SqlContext.TriggerContext.TriggerAction.ToString()}";

    // ***************************************************************

    try
    {
        // extract data involved in trigger
        // Create the Event object
        EventGridEvent evt = new EventGridEvent("QWDBEvent", eventType, new
                      TriggerData(SqlContext.TriggerContext, SqlContext.Pipe));

        // Publish the event
        Event.Publish(topicHost, topicKey, evt);
    }
    catch (Exception ex)
    {
        //TODO - how do we handle these through SQL CLR? 
        // Going with a fire-and-forget for now    
        SqlContext.Pipe.Send($"Failure firing {ex.Message}");        
    }
    SqlContext.Pipe.Send($"Trigger fired");
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-04 17:06:17

这不是本地支持的,也不是非常容易实现的。实际上,我有一个模拟,但没有时间发表它。当然不是直接前进。现在,您可以看看这两个问题的答案:

SQL CLR Trigger - get source table

我会更新这个答案,当我得到我的解决方案清理和张贴。

但是,虽然您说只有几个表将被应用于此,但请记住触发器是在DML (甚至DDL)语句是其一部分的事务上下文中执行的。这有两个后果:

  1. 触发器花费的时间越长,DML / DDL操作所需的时间就越长,因此对象上的锁保持的时间也就越长。这可能会对并发/性能产生不利影响。这让许多人非常紧张,以至于将DML / DDL语句与本地(intranet /同一网络)服务的web服务调用绑定在一起,但在整个互联网上,这给一个应该相当简单的过程带来了一种危险的、高度可变的风险。当然,如果您使用的是Azure VM或Azure SQL托管实例,那么可能延迟时间很低--足够安全“足够”。不管怎么说,都要小心!(需要明确的是:使用the触发器执行SQLCLR存储过程不会减轻这种风险;这仍然是相同的transaction)
  2. if触发器会失败/抛出错误,默认情况下会中止事务并回滚DML (或DDL)操作。这是故意的行为吗?通常,记录事件的失败不应该终止操作本身,对吗?因此,您可能需要吞下错误(或者至少将其写入文本文件)。

通过设置service来处理调用日志服务,您应该能够将DML/DLL操作与日志记录块分离开来。在这种情况下,您可以:

  1. 使用trg触发器
    1. 通过以下方式获取表名:选择tab.name从sys.objects选项卡tab.object_id =(从sys.objects trg选择trg.parent_object_id,trg.object_id = @@PROCID );info

  • 可以从INSERTED和/或DELETED表收集任何其他信息以进行日志记录(在此之后,您将无法访问这些表;尽管您可以将这两个表中的数据重新打包为XML作为Service消息的一部分发送--例如SELECT * FROM inserted FOR XML RAW('ins'); )为Service排队发送消息,包括收集到的INSERTED消息

使用Service operations

  • can

  • 将异步处理来自DML / DLL network)

的消息,执行SQLCLR存储过程,传递收集到的to触发器中的信息,以调用日志服务(无论是内部还是外部network))。

请记住(因为您提到了从INSERTED表和DELETED表中获得受影响的PK值),如果DML操作影响多行,这些表中可能有多个行(即,对于DML操作永远不要假设为一行)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60060272

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档