SqlBulkCopy 出错:字符无效,但 XML 字符串似乎有效
Error with SqlBulkCopy: invalid character but the XML string seems to be valid
我在使用 SqlBulkCopy(在 c# 框架 4.5.1 中)时遇到问题,其中有效的 XML 字符串导致错误 System.Data.SqlClient.SqlException: {"XML parsing: line 1, character 29, A string literal was expected"}""
table 是...
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]
XML 的 SQL 插入(工作正常)是...
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>'
)
我用来创建空 DataTable 的 C# 代码是...
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 后,调用执行大容量复制的 c# 方法...
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 数据列 BigXML 的数据类型为 System.String,最大长度为 -1。谁能告诉我这是怎么回事?
错误信息指向第1行,字符29...
此时 default-namespace-attribute 需要一个字符串文字...您在双引号中提供了名称空间。所以一切似乎都很好,但是:
有几个帖子 (e.g. this one) 指出了与 SqlBulkCopy
和双引号有关的问题。
您可以尝试以下方法:
使用单引号而不是双引号:<ArrayOfTriggerEvent xmlns='Your namespace' NextAttr='SomeVAlue' ...
尝试转义 "
字符。通常,这是通过将符号加倍 (xmlns=""Your namespace""
) 或使用转义字符来完成的。尝试 \"
、^"
或反引号 (`"
)...
我在使用 SqlBulkCopy(在 c# 框架 4.5.1 中)时遇到问题,其中有效的 XML 字符串导致错误 System.Data.SqlClient.SqlException: {"XML parsing: line 1, character 29, A string literal was expected"}""
table 是...
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]
XML 的 SQL 插入(工作正常)是...
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>'
)
我用来创建空 DataTable 的 C# 代码是...
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 后,调用执行大容量复制的 c# 方法...
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 数据列 BigXML 的数据类型为 System.String,最大长度为 -1。谁能告诉我这是怎么回事?
错误信息指向第1行,字符29...
此时 default-namespace-attribute 需要一个字符串文字...您在双引号中提供了名称空间。所以一切似乎都很好,但是:
有几个帖子 (e.g. this one) 指出了与 SqlBulkCopy
和双引号有关的问题。
您可以尝试以下方法:
使用单引号而不是双引号:
<ArrayOfTriggerEvent xmlns='Your namespace' NextAttr='SomeVAlue' ...
尝试转义
"
字符。通常,这是通过将符号加倍 (xmlns=""Your namespace""
) 或使用转义字符来完成的。尝试\"
、^"
或反引号 (`"
)...