C# SqlBulkCopy-数据源中类型字符串的给定值无法转换为指定目标列的类型money
我在尝试从DataTable执行SqlBulkCopy时遇到此异常C# SqlBulkCopy-数据源中类型字符串的给定值无法转换为指定目标列的类型money,c#,datatable,sqlbulkcopy,C#,Datatable,Sqlbulkcopy,我在尝试从DataTable执行SqlBulkCopy时遇到此异常 Error Message: The given value of type String from the data source cannot be converted to type money of the specified target column. Target Site: System.Object ConvertValue(System.Object, System.Data.SqlClient._SqlMe
Error Message: The given value of type String from the data source cannot be converted to type money of the specified target column.
Target Site: System.Object ConvertValue(System.Object, System.Data.SqlClient._SqlMetaData, Boolean, Boolean ByRef, Boolean ByRef)
我理解错误的意思,但如何获得更多信息,例如发生错误的行/字段?datatable由第三方填充,最多可包含200列和10k行。返回的列取决于发送给第三方的请求。所有数据表列都是字符串类型。我的数据库中的列并不都是varchar,因此,在执行insert之前,我使用以下代码格式化datatable值(删除了不重要的代码):
3级异常有以下错误:
Error Message: Failed to convert parameter value from a String to a Decimal.
Target Site: System.Object CoerceValue(System.Object, System.Data.SqlClient.MetaType, Boolean ByRef, Boolean ByRef, Boolean)
Error Message: Input string was not in a correct format
Target Site: Void StringToNumber(System.String, System.Globalization.NumberStyles, NumberBuffer ByRef, System.Globalization.NumberFormatInfo, Boolean)
有人有什么想法要解决吗?或者有什么想法来获取更多信息?@Corey-它只是简单地删除所有无效字符。然而,你的评论让我想到了答案 问题是我数据库中的许多字段都可以为空。使用SqlBulkCopy时,不会将空字符串作为空值插入。因此,在我的字段不是varchar(bit、int、decimal、datetime等)的情况下,它试图插入一个空字符串,这显然对该数据类型无效 解决方案是修改我的循环,在这里我将值验证为这个值(对每个不是字符串的数据类型重复)
在进行上述调整后,所有内容都会无问题插入。对于遇到此问题并收到与nvarchar(而非金钱)相关的类似错误消息的人: 无法将数据源中给定的字符串类型值转换为指定目标列的nvarchar类型 这可能是由于列太短造成的 例如,如果您的列定义为
nvarchar(20)
,并且您有一个40个字符的字符串,则可能会出现此错误
请使用SqlBulkCopyColumnMapping 例如:
private void SaveFileToDatabase(string filePath)
{
string strConnection = System.Configuration.ConfigurationManager.ConnectionStrings["MHMRA_TexMedEvsConnectionString"].ConnectionString.ToString();
String excelConnString = String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0\"", filePath);
//Create Connection to Excel work book
using (OleDbConnection excelConnection = new OleDbConnection(excelConnString))
{
//Create OleDbCommand to fetch data from Excel
using (OleDbCommand cmd = new OleDbCommand("Select * from [Crosswalk$]", excelConnection))
{
excelConnection.Open();
using (OleDbDataReader dReader = cmd.ExecuteReader())
{
using (SqlBulkCopy sqlBulk = new SqlBulkCopy(strConnection))
{
//Give your Destination table name
sqlBulk.DestinationTableName = "PaySrcCrosswalk";
// this is a simpler alternative to explicit column mappings, if the column names are the same on both sides and data types match
foreach(DataColumn column in dt.Columns) {
s.ColumnMappings.Add(new SqlBulkCopyColumnMapping(column.ColumnName, column.ColumnName));
}
sqlBulk.WriteToServer(dReader);
}
}
}
}
}
检查正在写入服务器的数据。可能是数据具有未使用的分隔符 像 您的分隔符是“|”,但数据有一个分隔符”。
因此,您将得到错误 确保在具有get set属性的实体类中添加的列值u的顺序也与目标表中的顺序相同。在尝试映射字符串长度的列时,还必须注意另一个问题, 例如
TK\u NO nvarchar(50)
您必须映射到
与目标字段的长度相同。因为我不相信
“请使用…”加上一些与问题无关的随机代码是一个很好的答案,但我相信精神是正确的,我决定正确回答这个问题
使用Sql大容量复制时,它会尝试将输入数据直接与服务器上的数据对齐。因此,它接受服务器表并执行类似以下内容的SQL语句:
INSERT INTO [schema].[table] (col1, col2, col3) VALUES
因此,如果您给它第1、3和2列,即使您的名字可能匹配(例如:col1、col3、col2)。它将这样插入:
INSERT INTO [schema].[table] (col1, col2, col3) VALUES
('col1', 'col3', 'col2')
Sql批量插入必须确定列映射,这将是额外的工作和开销。所以它允许你选择。。。请确保代码和SQL表列的顺序相同,或者显式声明按列名对齐
因此,如果您的问题是列对齐错误,这可能是导致此错误的主要原因,那么这个答案适合您
太长,读不下去了
使用系统数据;
//...
myDataTable.Columns.Cast().ToList().ForEach(x=>
添加(新的SqlBulkCopyColumnMapping(x.ColumnName,x.ColumnName));
这将获取您试图插入到已创建的BulkCopy对象中的现有DataTable,它只会显式地将名称映射到名称。当然,如果出于某种原因,您决定以不同于SQL Server列的方式命名DataTable列。。。这是你的责任。不是每个人都能解决的问题,但对我来说:
所以,我遇到了这个问题。我似乎遇到的问题是,我的DataTable没有ID列,但目标目的地有一个带有主键的列
当我调整数据表使其具有id时,副本工作得非常好
在我的场景中,Id列对于主键不是很重要,因此我从目标目标表中删除了该列,并且SqlBulkCopy正常工作。我的问题在于列映射,而不是值。我从一个开发系统中提取内容,创建目标表,批量复制内容,从prod系统中提取内容,调整目标表,批量复制内容,使两个批量复制的列顺序不匹配
//即使源和目标列名
//与列顺序相同将影响大容量复制,从而导致数据转换错误
foreach(p_dataTable.Columns中的DataColumn列)
{
bulkCopy.ColumnMappings.Add(
新的()
{
SourceColumn=column.ColumnName,
DestinationColumn=column.ColumnName
}
);
}
bulkCopy.WriteToServer(p_数据表);
查看文档时,可以使用属性,该属性将在复制N行时引发事件。它可以帮助您计算发生默认值的行所在的批处理。您的CleanDecimal
方法是尝试验证数据,还是仅删除无效字符?您是否尝试过使用Decimal.TryParse()
查看数据的格式是否正确?试一试,看看它是否出现了有问题的值。如果您查看问题的代码示例,就会发现正在设置ColumnMappings。这与映射列无关,而是与进入这些列的数据格式有关。尽管他们说SqlBulkCopy自动映射这些列,
045|2272575|0.000|0.000|2013-10-07
045|2272585|0.000|0.000;2013-10-07
INSERT INTO [schema].[table] (col1, col2, col3) VALUES
INSERT INTO [schema].[table] (col1, col2, col3) VALUES
('col1', 'col3', 'col2')
using System.Data;
//...
myDataTable.Columns.Cast<DataColumn>().ToList().ForEach(x =>
bulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping(x.ColumnName, x.ColumnName)));