AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 128695
Accepted
Bogdan Bogdanov
Bogdan Bogdanov
Asked: 2016-02-10 00:42:22 +0800 CST2016-02-10 00:42:22 +0800 CST 2016-02-10 00:42:22 +0800 CST

Erro SQL 2012 CLR: "A transação de contexto que estava ativa antes de inserir ..."?

  • 772

Estou experimentando um erro estranho com SQL 2012e CLR:

A transação de contexto que estava ativa antes de entrar na rotina definida pelo usuário, disparar ou agregar "Minha rotina" foi finalizada dentro dela, o que não é permitido. Altere a lógica do aplicativo para impor o aninhamento estrito da transação.

Não tenho ideia do que pode ser o problema. Alguém pode me dar alguma direção onde procurar?

Em geral, tenho um procedimento armazenado SQL dentro do qual, na UPDATEcláusula, chamo scalar CLR function. A função recebe 2 xmlstrings: uma para xmle outra para xsduma validação de make. A função é chamada várias vezes na consulta.

EDITAR:

Mensagem de erro:

Número do erro: 3991

Gravidade do erro: 16

Estado de erro: 1

Procedimento de erro: sproc_XXX

Linha de erro: 297

Mensagem de erro: A transação de contexto que estava ativa antes de entrar na rotina definida pelo usuário, gatilho ou agregado "CLR_XXX_Xml" foi finalizada dentro dela, o que não é permitido. Altere a lógica do aplicativo para impor o aninhamento estrito da transação.

EDIÇÃO 2:

Eu acho o problema. Quando usamos CLRpara validar XML, sned 1º parâmetro para ser o XSDnome. Em seguida CLR, extraímos o XSDesquema do SQL Server. No nosso caso, temos uma string vazia para o XSDnome, mas mesmo assim try / catcho erro é passado para o procedimento armazenado do SQL Server.

Nossa função retorna 0 / 1então os registros com 0 devem ser atualizados com código de erro.

Mas neste caso recebemos exceção no SQL.

Meu código é:

SQL para atualização

UPDATE FR
SET ErrorCode = 'OUR ERROR CODE'
FROM dbo.DataTable FR
INNER JOIN dbo.TempTable FRN ON (FRN.SessionGUID = @sSessionGUID)
    AND (FRN.IDLog = FR.IDLog)
    AND (FRN.UniqueID = FR.UniqueID)
    AND (
        (FRN.Template LIKE '%##%')
        OR (PANI_Core.dbo.funCLRs_CheckXML('schRPT_' + @sSchema + '_Peliminary', 
     FRN.Template) <> 1)
        OR (NULLIF(FRN.Template, '') IS NULL)
        OR (
            (TRY_CONVERT(DATE, FRN.ExpirationDate) IS NULL)
            AND (NULLIF(FRN.ExpirationDate, '') IS NOT NULL)
            )
        OR (
            (TRY_CONVERT(VARCHAR(35), FRN.EGN) IS NULL)
            AND (NULLIF(FRN.EGN, '') IS NOT NULL)
            )
        OR (NULLIF(FRN.EGN, '') IS NULL)
        OR (
            (TRY_CONVERT(MONEY, FRN.Amount) IS NULL)
            AND (NULLIF(FRN.Amount, '') IS NOT NULL)
            )
        OR (NULLIF(FRN.Amount, '') IS NULL)
        OR (
            (TRY_CONVERT(VARCHAR(32), FRN.UniqueClientID) IS NULL)
            AND (NULLIF(FRN.UniqueCID, '') IS NOT NULL)
            )
        OR (NULLIF(FRN.UniqueCID, '') IS NULL)
        )
WHERE (FR.IDLog = @IDLog)
    AND (FR.ErrorCode IS NULL);

Código CLR:

public static SqlBoolean funCLRs_CheckXml(SqlString XsdSchemaString, SqlString ValueString)
{
    XmlDocument asset1 = new XmlDocument();
    XmlSchema schema1 = new XmlSchema();
    System.Text.StringBuilder o = new System.Text.StringBuilder();
    using (SqlConnection sqlLocalConn = new SqlConnection("context connection=true;"))
    {
        try
        {
            if (XsdSchemaString.ToString().Length == 0)
            {
                try
                {
                    asset1.LoadXml(ValueString.ToString());
                    asset1 = null;
                    return new SqlBoolean(true);
                }
                catch (Exception ex)
                {
                    return new SqlBoolean(false);
                }
            }
            else
            {
                sqlLocalConn.Open();

                SqlCommand cmd = new SqlCommand("SELECT XML_SCHEMA_NAMESPACE (N'dbo', N'" + XsdSchemaString.ToString() + "')", sqlLocalConn);
                cmd.CommandTimeout = 240;

                SqlDataReader reader = cmd.ExecuteReader();
                if (reader.Read())
                {
                    SqlXml xmlData = reader.GetSqlXml(0);
                    using (XmlReader xmlReader = xmlData.CreateReader())
                    {
                        schema1 = XmlSchema.Read(xmlReader, ValidateSchema);
                    }

                    asset1.Schemas.Add(schema1);

                    XDocument oDoc = new XDocument();
                    oDoc = XDocument.Parse(ValueString.ToString());
                    oDoc.Descendants().Where(e => string.IsNullOrEmpty(e.Value)).Remove();

                    asset1.LoadXml(oDoc.FirstNode.ToString());
                    oDoc = null;

                    asset1.Validate((o1, e) =>
                    {
                        if (e.Severity == XmlSeverityType.Error)
                        {
                            o.AppendLine("Error: " + e.Message);
                        }
                    });

                    if (asset1.SchemaInfo.Validity == XmlSchemaValidity.Valid)
                    {
                        asset1 = null;
                        return new SqlBoolean(true);
                    }
                    else
                    {
                        asset1 = null;
                        return new SqlBoolean(false);
                    }
                }
                else
                {
                    asset1 = null;
                    return new SqlBoolean(false);
                }
            }
        }
        catch (Exception ex)
        {
            return new SqlBoolean(false);
        }
        finally
        {
            schema1 = null;
            asset1 = null;
            o = null;
        }
    }
}
transaction sql-server-2012
  • 1 1 respostas
  • 3345 Views

1 respostas

  • Voted
  1. Best Answer
    Solomon Rutzky
    2016-02-10T08:44:50+08:002016-02-10T08:44:50+08:00

    A causa direta do erro " A transação de contexto que estava ativa antes de entrar na rotina, gatilho ou agregado definido pelo usuário"..." foi finalizada dentro dela, o que não é permitido. " é:

    Você está chamando a função interna XML_SCHEMA_NAMESPACE() e, às vezes, ela falha devido a não encontrar a Coleção de Esquema XML especificada. De acordo com as informações da pergunta, você está passando uma string vazia quando esse erro ocorre, embora passar qualquer string que não corresponda a uma coleção de esquema XML existente causaria esse erro.

    O que está acontecendo é que você está atualmente em uma transação quando esta função SQLCLR é chamada (ou seja, a transação da UPDATEinstrução), e a XML_SCHEMA_NAMESPACEfalha é um erro de cancelamento de lote, caso em que a transação é revertida automaticamente (portanto try...catch, no O código .NET não pode ajudar aqui). Este é realmente o mesmo erro que você obteria se tivesse chamadas de Procedimento Armazenado aninhadas onde o Procedimento Armazenado externo iniciou uma Transação e o Procedimento Armazenado interno emitiu um ROLLBACK, caso em que o valor de @@TRANCOUNTseria menor ao sair do Procedimento Armazenado interno do que quando digitá-lo, e você receberia um erro informando que os valores inicial e final de @@TRANCOUNTnão eram os mesmos.

    Aqui está um código de exemplo mostrando que a XML_SCHEMA_NAMESPACEfalha é um erro de cancelamento de lote (e, portanto, de transação):

    BEGIN TRAN;
    PRINT @@TRANCOUNT;
    DECLARE @SchemaCollectionName sysname = N'f';
    PRINT CONVERT(NVARCHAR(4000), XML_SCHEMA_NAMESPACE(N'dbo', @SchemaCollectionName));
    GO
    PRINT @@TRANCOUNT;
    ROLLBACK;
    

    Retorna:

    1
    Msg 6314, Nível 16, Estado 1, Linha 4
    A coleção especificada não existe nos metadados: 'f'
    0
    Msg 3903, Nível 16, Estado 1, Linha 7
    A solicitação ROLLBACK TRANSACTION não tem BEGIN TRANSACTION correspondente.

    A causa raiz desse erro é:

    Você está permitindo que valores sejam passados ​​para a XML_SCHEMA_NAMESPACEfunção que causam erro, especificamente uma string vazia.

    A correção para esse erro é fazer o seguinte:

    1. Teste também NULLvalores de string com espaço em branco. Isso evitará erros devido a NULLvalores (o que causaria um erro em seu código atual de qualquer maneira), bem como strings não vazias preenchidas com qualquer combinação de espaços, tabulações, retornos, etc. (o IsNullOrWhiteSpacemétodo verifica todos os caracteres de espaço em branco Unicode ). Substitua:
      if (XsdSchemaString.ToString().Length == 0)
      por:
      if (XsdSchemaString.IsNull || String.IsNullOrWhiteSpace(XsdSchemaString.Value))
    2. Faça uma verificação de existência para o nome da Coleção de Esquema XML que está sendo passado, antes da chamada, XML_SCHEMA_NAMESPACEpara que você só chame essa função se o nome realmente existir. Você pode fazer isso na mesma etapa da corrente SELECT, envolvendo-a em um IF EXISTS:

      DECLARE @SchemaCollectionName NVARCHAR(128) = N'not here';
      IF (EXISTS(
              SELECT  *
              FROM        sys.xml_schema_collections
              WHERE   [schema_id] = SCHEMA_ID(N'dbo')
              AND     [name] = @SchemaCollectionName
              )
          )
      BEGIN
          SELECT XML_SCHEMA_NAMESPACE(N'dbo', @SchemaCollectionName) AS [MyXSD];
      END;
      

      Isso evitará erros devido a valores incorretos não vazios e sem apenas espaços em branco. Um valor incorreto não retornará um conjunto de resultados e seu código já trata isso como elsecondição para if (reader.Read()).

    3. Embora não seja crítico para esse problema, seria melhor parametrizar essa consulta. O código de exemplo em ambos os lugares mostra que a função aceita uma variável para o nome da Coleção de Esquema XML.
    • 2

relate perguntas

  • Diferença entre Flashback Query e Modo de Transação Serializável?

  • Qual é o termo correto para descrever uma "transação persistente"?

  • Por que as sequências Denali devem ter um desempenho melhor do que as colunas de identidade?

  • O SQL Server não deveria oferecer suporte a RANGE?

  • O que é SQL Server "Denali"? O que há de novo?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve