我有一个CLR触发器,它使用BeginInvoke
调用存储过程。在存储过程中,我尝试调用SqlComman,但我得到:请求的操作需要一个Sql Server执行线程。当前线程由用户代码或其他非Sql Server引擎代码启动。
我必须在SP中执行此操作,因为等待,我必须使用BeginInvoke
调用SP。
代码:
[SqlProcedure()]
public static void MySendData( String crudType, String sourceTable, ... ) {
SqlCommand sqlDeleteComm;
String temp = String.Empty;
using( SqlConnection conn = new SqlConnection( "context connection=true" ) ) {
sqlDeleteComm = new SqlCommand( "DELETE FROM #TEMP_TABLE" );
sqlDeleteComm.Connection = conn;
try {
conn.Open();
sqlDeleteComm.ExecuteNonQuery();
conn.Close();
} catch( Exception ex ) {
// --- here ---
// The requested operation requires a Sql Server execution thread. The current thread was started by user code or other non-Sql Server engine code.
}
}
...
}
[Microsoft.SqlServer.Server.SqlTrigger( Name = "MyTrigger", Target = "MyTable", Event = "FOR UPDATE, INSERT, DELETE" )]
public static void MyTrigger() {
SqlTriggerContext myContext = SqlContext.TriggerContext;
MyDelagate d;
SqlCommand sqlComm;
SqlDataReader reader;
if( connection.State != ConnectionState.Open ) {
connection.Open();
}
switch( myContext.TriggerAction ) {
case TriggerAction.Update:
sqlComm = new SqlCommand( "SELECT X, Y FROM Inserted" );
sqlComm.Connection = connection;
reader = sqlComm.ExecuteReader();
try {
reader.Read();
d = new MyDelagate( MySendData );
d.BeginInvoke( "Update", "MyTable", ( Int32 )reader[ 0 ], ( Int32 )reader[ 1 ], null, null );
} catch( Exception ex ) {
} finally {
reader.Close();
}
break;
...
}
}
对于所有在SP中调用SQL查询的人,我怎么能这样做?
答案 0 :(得分:1)
您不能在线程之外使用上下文连接SQL Server运行您的CLR代码;这是为了确保服务器的可靠性 - SQL Server使用自定义CLR托管,我很惊讶它允许你自己创建自己的线程。您可以使用T-SQL从MySendData
调用MyTrigger
,使用上下文SqlCommand
上的标准ADO.NET SqlConnection
,但无法单独运行线。如果您真的想在数据库级别上进行异步/并行,请查看SQL Server Broker。
答案 1 :(得分:0)
如果可以避免使用上下文连接,则可以避免此问题。使用常规的连接字符串(将Enlist选项设置为false,以防止在必要时阻止使用同一事务上下文)创建新的SqlConnection,将允许您在SQL CLR上下文中使用多线程。