简体   繁体   English

CLR存储过程需要Sql Server执行线程

[英]CLR Stored Procedure needs a Sql Server execution thread

I've a CLR trigger, which calls a Stored Procedure with BeginInvoke . 我有一个CLR触发器,它使用BeginInvoke调用存储过程。 In the Stored Procedure I try to call an SqlComman, but I get: The requested operation requires a Sql Server execution thread. 在存储过程中,我尝试调用SqlComman,但得到: 请求的操作需要Sql Server执行线程。 The current thread was started by user code or other non-Sql Server engine code. 当前线程由用户代码或其他非SQL Server引擎代码启动。

I have to do this things in the SP, and I have to call the SP with BeginInvoke , because of the waiting. 我必须在SP中执行此操作,并且由于等待,我必须使用BeginInvoke调用SP。

The code: 编码:

[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;
            ...
    }
}

How could I, for all that call SQL queries in the SP? 对于SP中所有调用SQL查询的人,我该怎么办?

You can't use the context connection outside of the thread SQL Server runs your CLR code in; 您不能在线程外部使用上下文连接SQL Server在其中运行CLR代码。 this is to ensure reliability of the server - SQL Server uses custom CLR hosting, and I'm surprised it allowed you to spin your own thread at all. 这是为了确保服务器的可靠性-SQL Server使用自定义CLR托管,我很惊讶它完全允许您旋转自己的线程。 You can call MySendData from MyTrigger with T-SQL, using standard ADO.NET SqlCommand on the context SqlConnection , but there is no way for it to run in a separate thread. 您可以使用SqlConnection上下文中的标准ADO.NET SqlCommand ,通过T-SQL从MyTrigger调用MySendData ,但是无法在单独的线程中运行它。 If you really want asynchrony/parrallelism on the database level, look into SQL Server Broker. 如果您确实希望在数据库级别实现异步/并行处理,请查看SQL Server Broker。

If you can avoid using the context connection you can circumvent this issue. 如果可以避免使用上下文连接,则可以避免此问题。 Creating a new SqlConnection with a conventional connection string (with the Enlist option set to false to prevent usage of the same transaction context if necessary) will allow you to use multithreading in a SQL CLR context. 使用常规的连接字符串(将Enlist选项设置为false,以防止在必要时阻止使用同一事务上下文)创建新的SqlConnection将使您能够在SQL CLR上下文中使用多线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM