Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# SqlBulkCopy-数据源中类型字符串的给定值无法转换为指定目标列的类型money_C#_Datatable_Sqlbulkcopy - Fatal编程技术网

C# SqlBulkCopy-数据源中类型字符串的给定值无法转换为指定目标列的类型money

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

我在尝试从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._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)));