调用使用CLR的存储过程时,SQL触发器失败

时间:2017-12-01 11:40:18

标签: c# sql-server stored-procedures triggers sqlclr

我在同一个SQL Server实例上有两个数据库

在'DatabaseA'中,我有一个存储过程调用C#代码(SQL中的CLR程序集)来解压缩数据,解包后将解压缩的数据写入DatabaseB的表(ScanTracking,Strings,Numerics)

手动执行时的存储过程可以正常工作。

但是当我通过DatabaseA中存在的表上的触发器运行存储过程时。我收到以下错误

'交易上下文由另一个会话'

使用

错误的全部细节如下:

Msg 6522, Level 16, State 1, Procedure ExecuteDeSerializeBulk, Line 0
A .NET Framework error occurred during execution of user-defined routine or aggregate "ExecuteDeSerializeBulk": 
System.Data.SqlClient.SqlException: Transaction context in use by another session.
System.Data.SqlClient.SqlException: 
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest)
   at System.Data.SqlClient.SqlInternalConnectionTds.PropagateTransactionCookie(Byte[] cookie)
   at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
   at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
   at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
   at System.Data.ProviderBase.DbConnectionPool.PrepareConnection(DbConnection owningObject, DbConnectionInternal obj, Transaction transaction)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnecti...
The statement has been terminated.

我做了一些研究,发现了以下链接

Transaction context in use by another session

https://learningintheopen.org/2014/01/21/technical-microsoft-sql-server-transact-sql-linked-server-error-transaction-context-in-use-by-another-session-msg-3910-level-16-state-2-line-1/

我没有使用链接服务器或任何复杂的,我的数据库都在同一台服务器上。

作为一种解决方法,我恢复了每隔5分钟运行一次的SQL代理作业,并将数据解压缩到DatabaseB上,这样可以正常工作。但是我的想法告诉我,我没有找到触发器问题的解决方案,并使用SQL代理作业来解决它。

任何想法或建议都会有很大帮助。

1 个答案:

答案 0 :(得分:0)

  

手动执行时的存储过程可以正常工作。

首先尝试执行BEGIN TRAN;,然后在测试时运行存储过程。这是错误的吗?它应该得到与从Trigger执行它时看到的相同的错误。触发器在系统启动的事务中执行,因此您所描述的内容是有意义的。

以下是一些尝试:

  1. 不是连接到DB来写任何东西,而是将值返回给调用进程,然后从那里进行写入。如果可以做的话,这是你最好的选择,因为它可以解除依赖关系,并为你提供更灵活的方式/时间/在何处使用SQLCLR代码。

  2. 使用Context Connection = true;作为连接字符串

  3. 在连接字符串中指定enlist=false;,以便不使用尝试附加到现有事务的默认行为。