Для хранимой процедуры CLR требуется поток выполнения сервера Sql

У меня есть триггер CLR, который вызывает хранимую процедуру с BeginInvoke, В хранимой процедуре я пытаюсь вызвать SqlComman, но получаю: Запрошенная операция требует выполнения потока Sql Server. Текущий поток был запущен с помощью пользовательского кода или другого кода ядра, отличного от Sql Server.

Я должен сделать это в SP, и я должен вызвать SP с BeginInvoke из-за ожидания.

Код:

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

Как я мог, для всех, которые вызывают запросы SQL в SP?

1 ответ

Решение

Вы не можете использовать контекстное соединение вне потока, в котором SQL Server запускает ваш код CLR; это сделано для обеспечения надежности сервера - SQL Server использует собственный хостинг CLR, и я удивлен, что он позволил вам вообще раскрутить свой собственный поток. Ты можешь позвонить MySendData от MyTrigger с T-SQL, используя стандарт ADO.NET SqlCommand в контексте SqlConnection, но нет возможности запустить его в отдельном потоке. Если вы действительно хотите асинхронность / параллелизм на уровне базы данных, посмотрите на SQL Server Broker.

Если вы можете избежать использования контекстного соединения, вы можете обойти эту проблему. Создание нового SqlConnection с обычной строкой подключения (с параметром Enlist, установленным в значение false, чтобы предотвратить использование того же контекста транзакции, если это необходимо), позволит вам использовать многопоточность в контексте SQL CLR.

Другие вопросы по тегам