2012-05-04 6 views

risposta

47

una delle colonne di dati nella excel (colonna ID 6) ha uno o più dati delle celle che superano la lunghezza DataColumn tipo di dati in il database.

Verificare i dati in Excel. Verificare inoltre che i dati in Excel per il formato siano conformi allo schema della tabella del database.

Per evitare questo, provare a superare la lunghezza dei dati del tipo di dati stringa nella tabella del database.

Spero che questo aiuti.

98

So che questo post è vecchio ma mi sono imbattuto in questo stesso problema e alla fine ho trovato una soluzione per determinare quale colonna stava causando il problema e riportarla come necessario. Ho finalmente capito che il colid che viene restituito in SqlException non è a base zero, quindi è necessario sottrarre 1 da esso per ottenere il valore. Dopodiché viene utilizzato come indice della _sortedColumnMappings ArrayList dell'istanza SqlBulkCopy e non dell'indice dei mapping delle colonne che sono stati aggiunti all'istanza SqlBulkCopy. Una cosa da notare è che SqlBulkCopy si fermerà al primo errore ricevuto, quindi questo potrebbe non essere l'unico problema, ma almeno aiuta a capirlo.

try 
{ 
    bulkCopy.WriteToServer(importTable); 
    sqlTran.Commit(); 
}  
catch (SqlException ex) 
{ 
    if (ex.Message.Contains("Received an invalid column length from the bcp client for colid")) 
    { 
     string pattern = @"\d+"; 
     Match match = Regex.Match(ex.Message.ToString(), pattern); 
     var index = Convert.ToInt32(match.Value) -1; 

     FieldInfo fi = typeof(SqlBulkCopy).GetField("_sortedColumnMappings", BindingFlags.NonPublic | BindingFlags.Instance); 
     var sortedColumns = fi.GetValue(bulkCopy); 
     var items = (Object[])sortedColumns.GetType().GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(sortedColumns); 

     FieldInfo itemdata = items[index].GetType().GetField("_metadata", BindingFlags.NonPublic | BindingFlags.Instance); 
     var metadata = itemdata.GetValue(items[index]); 

     var column = metadata.GetType().GetField("column", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(metadata); 
     var length = metadata.GetType().GetField("length", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(metadata); 
     throw new DataFormatException(String.Format("Column: {0} contains data with a length greater than: {1}", column, length)); 
    } 

    throw; 
}
+2

Questo funziona molto bene, grazie per richiedente. – Steven

+0

Sai se è possibile ottenere anche il numero di riga? –

+0

Da dove ricevi DataFormatException? Questa è una classe locale per il tuo progetto? Anche il tuo codice mangia tutte le altre eccezioni sql ... forse fai un rethrow? – OmegaMan

0

ho affrontato un simile tipo di problema durante il passaggio di una stringa di tabella di database utilizzando l'opzione SQL BulkCopy. La stringa che stavo passando era di 3 caratteri mentre la lunghezza della colonna di destinazione era varchar(20). Ho provato a tagliare la stringa prima di inserirla in DB usando la funzione Trim() per verificare se il problema era dovuto a uno spazio (iniziale e finale) nella stringa. Dopo aver tagliato la corda, ha funzionato bene.

Si può provare text.Trim()

0

Grande pezzo di codice, grazie per la condivisione!

Ho finito utilizzando il reflection per ottenere il DataMemberName effettivo da restituire a un client su un errore (sto utilizzando il salvataggio di massa in un servizio WCF). Speriamo che qualcun altro possa scoprire come l'ho fatto utile.

static string GetDataMemberName(string colName, object t) { 
 
    foreach(PropertyInfo propertyInfo in t.GetType().GetProperties()) { 
 
    if (propertyInfo.CanRead) { 
 
     if (propertyInfo.Name == colName) { 
 
     var attributes = propertyInfo.GetCustomAttributes(typeof(DataMemberAttribute), false).FirstOrDefault() as DataMemberAttribute; 
 
     if (attributes != null && !string.IsNullOrEmpty(attributes.Name)) 
 
      return attributes.Name; 
 
     return colName; 
 
     } 
 
    } 
 
    } 
 
    return colName; 
 
}

0

controllare la dimensione delle colonne della tabella che si sta facendo grosso inserto/copia. potrebbe essere necessario estendere il varchar o altre colonne di stringhe o il valore che si sta inserendo deve essere tagliato. Anche l'ordine delle colonne dovrebbe essere uguale a quello della tabella.

ad esempio, aumentare le dimensioni della colonna varchar 30-50 =>

ALTER TABLE [dbo]. [TableName] ALTER COLUMN [ColumnName] Varchar si (50)

Problemi correlati