2012-05-04 507 views

回答

47

一個以Excel(列標識6)中的數據列的具有超過在數據類型的DataColumn長度的一個或更多個單元中的數據數據庫。

驗證excel中的數據。同時驗證Excel格式中的數據是否符合數據庫表模式。

要避免這種情況,請嘗試超過數據庫表中字符串數據類型的數據長度。

希望這會有所幫助。

98

我知道這篇文章是舊的,但我遇到了同樣的問題,並最終找出瞭解決方案,以確定哪個列導致問題並根據需要回報。我終於明白,在SqlException中返回的colid不是基於零的,因此您需要從中減去1以獲取該值。之後,它將用作SqlBulkCopy實例的_sortedColumnMappings ArrayList的索引,而不是添加到SqlBulkCopy實例的列映射的索引。有一點需要注意的是,SqlBulkCopy將停止收到的第一個錯誤,所以這可能不是唯一的問題,但至少有助於弄清楚。

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

這工作得非常好,謝謝你提交。 – Steven

+0

你知道是否有可能也得到行nr? –

+0

你從哪裏得到DataFormatException?這是你的項目的本地類嗎?另外你的代碼吃所有其他的SQL例外...也許做一個rethrow? – OmegaMan

0

我在使用SQL BulkCopy選項將字符串傳遞給數據庫表時遇到了類似的問題。我傳遞的字符串是3個字符,而目標列長度是varchar(20)。在使用Trim()函數插入到DB之前,我嘗試修剪字符串,以檢查問題是否由於字符串中的任何空格(前導和尾隨)而引起。修剪完字符串後,它工作正常。

您可以嘗試text.Trim()

0

大的一段代碼,謝謝你的分享!

我結束了使用反射來獲取實際的DataMemberName返回給客戶端的錯誤(我在WCF服務中使用批量保存)。希望別人會發現我是如何做到的。

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

檢查表你正在做批量插入/複製列的大小。 varchar或其他字符串列可能需要擴展或者您插入的值需要修剪。列順序也應與表中相同。

例如,增加varchar列30〜50的大小=>

ALTER TABLE [DBO]。[表名] ALTER COLUMN [的ColumnName] VARCHAR(50)