我有一个SQL CLR存储过程,该存储过程注册了一个事件处理程序以完成当前事务
[SqlProcedure]
public static void MySProc()
{
Transaction.Current.TransactionCompleted += new TransactionCompletedEventHandler(Current_TransactionCompleted);
Transaction.Current.Rollback(); //###Current_TransactionCompleted called here###
}
static void Current_TransactionCompleted(object sender, TransactionEventArgs e)
{
}
这是T-SQL调用代码
begin tran
EXEC [dbo].[MySProc]
commit tran
这按预期工作:在调用“ Transaction.Current.Rollback()”后,处理程序被执行。
但是,我感兴趣的是在“ MySProc()”以外完成事务时调用我的处理程序(或我的代码)。
[SqlProcedure]
public static void MySProc()
{
Transaction.Current.TransactionCompleted += new TransactionCompletedEventHandler(Current_TransactionCompleted);
}
static void Current_TransactionCompleted(object sender, TransactionEventArgs e)
{
}
begin tran
EXEC [dbo].[MySProc]
rollback tran -- ###Current_TransactionCompleted NOT called###
这可能吗? 如果没有,还有其他方法可以挂钩当前事务完成并在事务结果(提交或回滚)上带有“最后的字眼”吗
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
起初我以为根本不可能,但是经过进一步的调查,我发现这是一定程度的。在我的第一个测试中,我正在通过SqlContext.Pipe.Send("...");调用处理程序时打印出一条消息。它从不显示任何内容,因此我认为没有被调用。但是,我忘记SqlContext了事件处理程序中没有活动对象,因为它与调用过程(即启动它的会话)断开了连接。一旦我切换到File.WriteAllText()在事件处理程序中使用,那么我可以看到确实在执行任何SQLCLR代码COMMIT或ROLLBACK在其之外调用了它。而且,我用的是Transaction.Current.TransactionCompleted一样的问题,而不是使用静态变量,就像我最初使用的那样。并且,由于我们引用的是“当前”事务(即它已经在上下文连接中被征募),因此无需征募任何东西。
但是,我应该澄清,在事务已提交或回滚之后,有效的“ this”只是使一些SQLCLR代码得到执行。我什至通过在开始事务和注册处理程序之后终止会话来进行测试,它确实触发了事件处理程序。
但是,大多数问题的措词与该问题标题的措词(加了强调)之间略有脱节- 尝试在交易完成时注册要运行的用户代码-因为它们似乎指示完成交易的不同时间处理程序应在何时运行。
如果没有,还有其他方法可以挂钩当前事务完成并在事务结果(提交或回滚)上带有“最后的字眼”吗?
我会说:不仅“不”(至少不是我所知道的),而且您也不希望它是“是”,因为交易可能由于各种原因而被杀死(死锁,会话被杀死,连接池执行sp_reset_connection,批处理级别错误,任何错误(如果XACT_ABORT是ON,等等),您确实不想干扰SQL Server管理事务的能力。
据我所知,最接近的是为“提交”和“回滚”创建SQLCLR方法(类似于问题中的示例代码),并要求您的使用仅使用那些SQLCLR存储过程来执行这些操作。
在SQLCLR事件处理程序运行后的COMMIT或ROLLBACK。这不是事件处理程序,它不是由结束事务的请求触发的,而是由实际完成的事务触发的。在这一点上,没有办法“说了最后一句话”。