SqlBulkCopy – La valeur donnée du type Ssortingng de la source de données ne peut pas être convertie en type money de la colonne cible spécifiée.

Je reçois cette exception lorsque j’essaie de créer une SqlBulkCopy à partir d’un DataTable.

Error Message: The given value of type Ssortingng 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) 

Je comprends ce que dit l’erreur, mais comment puis-je obtenir plus d’informations, telles que la ligne / le champ concerné? Le datatable est peuplé par une tierce partie et peut contenir jusqu’à 200 colonnes et 10 000 lignes. Les colonnes renvoyées dépendent de la demande envoyée à la 3ème partie. Toutes les colonnes datatable sont de type chaîne. Les colonnes de ma firebase database ne sont pas toutes varchar. Par conséquent, avant d’exécuter l’insertion, je formate les valeurs pouvant être datées à l’aide du code suivant (le code non important a été supprimé):

 //--- create lists to hold the special data type columns List IntColumns = new List(); List DecimalColumns = new List(); List BoolColumns = new List(); List DateColumns = new List(); foreach (DataColumn Column in dtData.Columns) { //--- find the field map that tells the system where to put this piece of data from the 3rd party FieldMap ColumnMap = AllFieldMaps.Find(a => a.SourceFieldID.ToLower() == Column.ColumnName.ToLower()); //--- get the datatype for this field in our system Type FieldDataType = Nullable.GetUnderlyingType(DestinationType.Property(ColumnMap.DestinationFieldName).PropertyType); //--- find the field data type and add to respective list switch (Type.GetTypeCode(FieldDataType)) { case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: { IntColumns.Add(Column); break; } case TypeCode.Boolean: { BoolColumns.Add(Column); break; } case TypeCode.Double: case TypeCode.Decimal: { DecimalColumns.Add(Column); break; } case TypeCode.DateTime: { DateColumns.Add(Column); break; } } //--- add the mapping for the column on the BulkCopy object BulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping(Column.ColumnName, ColumnMap.DestinationFieldName)); } //--- loop through all rows and convert the values to data types that match our database's data type for that field foreach (DataRow dr in dtData.Rows) { //--- convert int values foreach (DataColumn IntCol in IntColumns) dr[IntCol] = Helpers.CleanNum(dr[IntCol].ToSsortingng()); //--- convert decimal values foreach (DataColumn DecCol in DecimalColumns) dr[DecCol] = Helpers.CleanDecimal(dr[DecCol].ToSsortingng()); //--- convert bool values foreach (DataColumn BoolCol in BoolColumns) dr[BoolCol] = Helpers.ConvertSsortingngToBool(dr[BoolCol].ToSsortingng()); //--- convert date values foreach (DataColumn DateCol in DateColumns) dr[DateCol] = dr[DateCol].ToSsortingng().Replace("T", " "); } try { //--- do bulk insert BulkCopy.WriteToServer(dtData); transaction.Commit(); } catch (Exception ex) { transaction.Rollback(); //--- handles error //--- this is where I need to find the row & column having an issue } 

Ce code doit formater toutes les valeurs pour leurs champs de destination. Dans le cas de cette erreur, la décimale, la fonction qui nettoie supprimera tout caractère autre que 0-9 ou. (virgule). Ce champ qui génère l’erreur serait nullable dans la firebase database.

L’exception de niveau 2 a cette erreur:

 Error Message: Failed to convert parameter value from a Ssortingng to a Decimal. Target Site: System.Object CoerceValue(System.Object, System.Data.SqlClient.MetaType, Boolean ByRef, Boolean ByRef, Boolean) 

et l’exception de niveau 3 a cette erreur:

 Error Message: Input ssortingng was not in a correct format Target Site: Void SsortingngToNumber(System.Ssortingng, System.Globalization.NumberStyles, NumberBuffer ByRef, System.Globalization.NumberFormatInfo, Boolean) 

Est-ce que quelqu’un a des idées à résoudre? ou des idées pour obtenir plus d’informations?

Pour les personnes qui tombent sur cette question et reçoivent un message d’erreur similaire en ce qui concerne un nvarchar au lieu d’argent:

La valeur donnée de type Ssortingng de la source de données ne peut pas être convertie en type nvarchar de la colonne cible spécifiée.

Cela pourrait être causé par une colonne trop courte.

Par exemple, si votre colonne est définie comme nvarchar(20) et que vous avez une chaîne de 40 caractères, vous pouvez obtenir cette erreur.

La source

Veuillez utiliser SqlBulkCopyColumnMapping.

Exemple:

 private void SaveFileToDatabase(ssortingng filePath) { ssortingng strConnection = System.Configuration.ConfigurationManager.ConnectionSsortingngs["MHMRA_TexMedEvsConnectionSsortingng"].ConnectionSsortingng.ToSsortingng(); Ssortingng excelConnSsortingng = Ssortingng.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(excelConnSsortingng)) { //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"; SqlBulkCopyColumnMapping AdmissionPaySrcID=new SqlBulkCopyColumnMapping("AdmissionPaySrcID","AdmissionPaySrcID"); sqlBulk.ColumnMappings.Add(AdmissionPaySrcID); SqlBulkCopyColumnMapping TMHP_Detail = new SqlBulkCopyColumnMapping("TMHP_Detail", "TMHP_Detail"); sqlBulk.ColumnMappings.Add(TMHP_Detail); SqlBulkCopyColumnMapping PaySrcType = new SqlBulkCopyColumnMapping("PaySrcType", "PaySrcType"); sqlBulk.ColumnMappings.Add(PaySrcType); SqlBulkCopyColumnMapping AgencyID = new SqlBulkCopyColumnMapping("AgencyID", "AgencyID"); sqlBulk.ColumnMappings.Add(AgencyID); SqlBulkCopyColumnMapping CountyCode = new SqlBulkCopyColumnMapping("CountyCode", "CountyCode"); sqlBulk.ColumnMappings.Add(CountyCode); SqlBulkCopyColumnMapping EntityID = new SqlBulkCopyColumnMapping("EntityID", "EntityID"); sqlBulk.ColumnMappings.Add(EntityID); sqlBulk.WriteToServer(dReader); } } } } } 

@Corey – Il supprime simplement tous les caractères non valides. Cependant, votre commentaire m’a fait penser à la réponse.

Le problème était que beaucoup de champs de ma firebase database sont nuls. Lors de l’utilisation de SqlBulkCopy, une chaîne vide n’est pas insérée en tant que valeur null. Ainsi, dans le cas de mes champs qui ne sont pas varchar (bits, entiers, décimaux, date / heure, etc.), il essayait d’insérer une chaîne vide, qui n’est évidemment pas valide pour ce type de données.

La solution a été de modifier ma boucle où je valide les valeurs (répétée pour chaque type de données qui n’est pas une chaîne)

 //--- convert decimal values foreach (DataColumn DecCol in DecimalColumns) { if(ssortingng.IsNullOrEmpty(dr[DecCol].ToSsortingng())) dr[DecCol] = null; //--- this had to be set to null, not empty else dr[DecCol] = Helpers.CleanDecimal(dr[DecCol].ToSsortingng()); } 

Après avoir effectué les réglages ci-dessus, tout est inséré sans problème.

Puisque je ne crois pas que "Please use..." plus some random code that is unrelated to the question est une bonne réponse, mais je crois que l’esprit était correct, j’ai décidé de répondre correctement.

Lorsque vous utilisez Sql Bulk Copy, il tente d’aligner vos données d’entrée directement sur les données du serveur. Donc, il faut la table de serveur et effectue une instruction SQL semblable à ceci:

 INSERT INTO [schema].[table] (col1, col2, col3) VALUES 

Par conséquent, si vous lui donnez les colonnes 1, 3 et 2, MÊME SI vos noms peuvent correspondre (par exemple: col1, col3, col2). Il insérera comme ceci:

 INSERT INTO [schema].[table] (col1, col2, col3) VALUES ('col1', 'col3', 'col2') 

Ce serait un travail supplémentaire et une surcharge pour l’insertion en vrac SQL de devoir déterminer un mappage de colonne. Cela vous permet donc de choisir … Assurez-vous que votre code et vos colonnes de la table SQL sont dans le même ordre, ou indiquez explicitement que vous souhaitez les aligner par nom de colonne.

Par conséquent, si votre problème est un mauvais alignement des colonnes, ce qui est probablement la majeure partie de la cause de cette erreur, cette réponse est pour vous.

TLDR

 using System.Data; //... myDataTable.Columns.Cast().ToList().ForEach(x => bulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping(x.ColumnName, x.ColumnName))); 

Cela prendra votre DataTable existant, que vous essayez d’insérer dans votre object BulkCopy créé, et il mappera simplement explicitement nom à nom. Bien sûr, si, pour une raison quelconque, vous avez décidé de nommer vos colonnes DataTable différemment de vos colonnes SQL Server … c’est sur vous.

Assurez-vous que les valeurs de colonne u ajoutées dans la classe d’entités ont également des propriétés get set dans le même ordre que celui présent dans la table cible.

il y a un autre problème que vous devez prendre en compte lorsque vous essayez de mapper la colonne: longueur de chaîne, par exemple TK_NO nvarchar (50), vous devez le mapper à la même longueur dans le champ de destination.

Vérifiez les données que vous écrivez sur le serveur. Peut-être que les données ont un délimiteur qui n’est pas utilisé.

comme

 045|2272575|0.000|0.000|2013-10-07 045|2272585|0.000|0.000;2013-10-07 

votre délimiteur est ‘|’ mais les données ont un délimiteur ‘;’ . Donc, pour cela, vous obtenez l’erreur.