Ошибка с SqlBulkCopy: недопустимый символ, но строка XML кажется допустимой

У меня возникла проблема с SqlBulkCopy (в С#, framework 4.5.1), где допустимая строка XML вызывает ошибку System.Data.SqlClient.SqlException: {"Синтаксический анализ XML: строка 1, символ 29, ожидался строковый литерал" }"

Стол...

CREATE TABLE [dbo].[JobManager_BigTextTest](
[PKID] [int] IDENTITY(1,1) NOT NULL,
[BigXML] [xml] NOT NULL, PK_JobManager_BigTextTest] PRIMARY KEY CLUSTERED 
(
    [PKID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Data]
) ON [Data] TEXTIMAGE_ON [Data]

SQL-вставка XML (которая отлично работает)...

INSERT INTO JobManager_BigTextTest
(
    BigXML
)
VALUES
(
    '<ArrayOfTriggerEvent xmlns="http://schemas.datacontract.org/2004/07/RRD.JobManager.AutomatedWorkScheduler.Triggers" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><TriggerEvent i:type="a:ScheduleEvent" xmlns:a="http://schemas.datacontract.org/2004/07/RRD.JobManager.AutomatedWorkScheduler.Triggers.Events"><a:Schedule i:type="b:IncrementalSchedule" xmlns:b="http://schemas.datacontract.org/2004/07/RRD.JobManager.AutomatedWorkScheduler.Schedules"><b:DaysOfMonth xmlns:c="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/><b:DaysOfWeek xmlns:c="http://schemas.datacontract.org/2004/07/System"/><b:Frequency>Daily</b:Frequency><b:LastDayOfMonth>false</b:LastDayOfMonth><b:LastExecuted i:nil="true"/><b:LastModified>2014-08-21T14:40:30.6116736-05:00</b:LastModified><b:EndTime i:nil="true"/><b:Increment>PT5M</b:Increment><b:StartTime>PT0S</b:StartTime></a:Schedule></TriggerEvent><TriggerEvent i:type="a:ScheduleEvent" xmlns:a="http://schemas.datacontract.org/2004/07/RRD.JobManager.AutomatedWorkScheduler.Triggers.Events"><a:Schedule i:type="b:SpecificSchedule" xmlns:b="http://schemas.datacontract.org/2004/07/RRD.JobManager.AutomatedWorkScheduler.Schedules"><b:DaysOfMonth xmlns:c="http://schemas.microsoft.com/2003/10/Serialization/Arrays"><c:int>8</c:int><c:int>11</c:int><c:int>24</c:int></b:DaysOfMonth><b:DaysOfWeek xmlns:c="http://schemas.datacontract.org/2004/07/System"/><b:Frequency>Monthly</b:Frequency><b:LastDayOfMonth>false</b:LastDayOfMonth><b:LastExecuted i:nil="true"/><b:LastModified>2014-08-21T14:40:30.6116736-05:00</b:LastModified><b:StartTimes xmlns:c="http://schemas.microsoft.com/2003/10/Serialization/Arrays"><c:duration>PT11H</c:duration><c:duration>PT11H30M</c:duration><c:duration>PT13H30M</c:duration></b:StartTimes></a:Schedule></TriggerEvent></ArrayOfTriggerEvent>'
)

Код С#, который я использовал для создания пустой таблицы данных,...

public static DataTable GetDataTableFromSqlDestination(string tableName)
{
    tableName = MakeInjectionProof(tableName); // error if injection discovered
    var dataTable = new DataTable();
    var query = $"SELECT * FROM [{tableName}] WHERE 1 = 0";

    using (var connection = new SqlConnection("my_connection"))
    using (var command = new SqlCommand(query, connection))
    {
        command.CommandTimeout = connection.ConnectionTimeout;
        command.CommandType = CommandType.Text;
        connection.Open();

        var da = new SqlDataAdapter(command);

        da.FillSchema(dataTable, SchemaType.Mapped);

        connection.Close();

        dataTable.PrimaryKey = null; // strip off primary key
        dataTable.Columns.Remove("PKID");
    }

    return dataTable;
}

После добавления строки (или строк) в DataTable вызывается метод С#, выполняющий массовое копирование...

public static void BulkCopyProcessChunk
(
    string tableName,
    DataTable dataTable,
    SqlConnection connection,
    SqlTransaction transaction
)
{
    using (var sbc = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transaction))
    {
        sbc.BulkCopyTimeout = 0; // Indefinite time out
        sbc.DestinationTableName = tableName;

        sbc.BatchSize = dataTable.Rows.Count;

        foreach (DataColumn r in dataTable.Columns)
        {
            sbc.ColumnMappings.Add(r.ColumnName, r.ColumnName);
        }

        sbc.WriteToServer(dataTable); // <--- error occurs here
    }
}

XML DataColumn, BigXML, имеет тип данных System.String с максимальной длиной -1. Кто-нибудь может сказать мне, что здесь происходит?


person Sam Jazz    schedule 13.12.2016    source источник
comment
Лучше всего запустить запрос в SQL Server Management Studio (SSMS), которая поставляется с SQL Server. Сообщение об ошибке в 100 раз лучше, чем в c#. С таблицами в С# обычно возникает -1, потому что таблица не построена или в таблице нет столбцов. Убедитесь, что вы не вызываете код из конструктора class.form. Он должен быть в методе загрузки формы после создания класса.   -  person jdweng    schedule 13.12.2016
comment
Я выполнил запрос, как указано выше, чтобы вставить ту же самую строку в ту же таблицу, и, похоже, с таблицей или строкой все в порядке.   -  person Sam Jazz    schedule 13.12.2016


Ответы (1)


Сообщение об ошибке указывает на строку 1, символ 29...

В этот момент атрибут default-namespace-attribute ожидает строковый литерал... Вы предоставляете пространство имен в двойных кавычках. Итак, вроде бы все в порядке, но:

Есть несколько сообщений (например, этот), указывающих на проблемы, связанные с SqlBulkCopy и двойные кавычки.

Вы можете попробовать следующее:

  • Используйте одинарные кавычки вместо двойных: <ArrayOfTriggerEvent xmlns='Your namespace' NextAttr='SomeVAlue' ...

  • Попробуйте избежать символа ". Обычно это делается либо удвоением знака (xmlns=""Your namespace""), либо с помощью escape-символа. Попробуйте \", ^" или обратную галочку (`")...

Еще немного информации об управляющих символах

person Shnugo    schedule 13.12.2016
comment
Я попытался использовать одинарные кавычки, и это удалось. Спасибо за помощь!!!! - person Sam Jazz; 14.12.2016