SqlBulkCopy Не Работает
у меня есть DataSet
заполняется из листа Excel. Я хотел использовать Sqlbulk Copy для вставки записей в Lead_Hdr
таблица, где LeadId
- Это ПК.
у меня есть следующая ошибка при выполнении кода ниже:
данное ColumnMapping не совпадать с любой колонки в источник или назначение
string ConStr=ConfigurationManager.ConnectionStrings["ConStr"].ToString();
using (SqlBulkCopy s = new SqlBulkCopy(ConStr,SqlBulkCopyOptions.KeepIdentity))
{
if (MySql.State==ConnectionState.Closed)
{
MySql.Open();
}
s.DestinationTableName = "PCRM_Lead_Hdr";
s.NotifyAfter = 10000;
#region Comment
s.ColumnMappings.Clear();
#region ColumnMapping
s.ColumnMappings.Add("ClientID", "ClientID");
s.ColumnMappings.Add("LeadID", "LeadID");
s.ColumnMappings.Add("Company_Name", "Company_Name");
s.ColumnMappings.Add("Website", "Website");
s.ColumnMappings.Add("EmployeeCount", "EmployeeCount");
s.ColumnMappings.Add("Revenue", "Revenue");
s.ColumnMappings.Add("Address", "Address");
s.ColumnMappings.Add("City", "City");
s.ColumnMappings.Add("State", "State");
s.ColumnMappings.Add("ZipCode", "ZipCode");
s.ColumnMappings.Add("CountryId", "CountryId");
s.ColumnMappings.Add("Phone", "Phone");
s.ColumnMappings.Add("Fax", "Fax");
s.ColumnMappings.Add("TimeZone", "TimeZone");
s.ColumnMappings.Add("SicNo", "SicNo");
s.ColumnMappings.Add("SicDesc", "SicDesc");
s.ColumnMappings.Add("SourceID", "SourceID");
s.ColumnMappings.Add("ResearchAnalysis", "ResearchAnalysis");
s.ColumnMappings.Add("BasketID", "BasketID");
s.ColumnMappings.Add("PipeLineStatusId", "PipeLineStatusId");
s.ColumnMappings.Add("SurveyId", "SurveyId");
s.ColumnMappings.Add("NextCallDate", "NextCallDate");
s.ColumnMappings.Add("CurrentRecStatus", "CurrentRecStatus");
s.ColumnMappings.Add("AssignedUserId", "AssignedUserId");
s.ColumnMappings.Add("AssignedDate", "AssignedDate");
s.ColumnMappings.Add("ToValueAmt", "ToValueAmt");
s.ColumnMappings.Add("Remove", "Remove");
s.ColumnMappings.Add("Release", "Release");
s.ColumnMappings.Add("Insert_Date", "Insert_Date");
s.ColumnMappings.Add("Insert_By", "Insert_By");
s.ColumnMappings.Add("Updated_Date", "Updated_Date");
s.ColumnMappings.Add("Updated_By", "Updated_By");
#endregion
#endregion
s.WriteToServer(sourceTable);
s.Close();
MySql.Close();
}
7 ответов
Ну, это правильно? Существуют ли имена столбцов с обеих сторон?
честно говоря, я никогда не возиться с картами. Мне нравится держать вещи простыми - у меня, как правило, есть промежуточная таблица, которая выглядит как ввод на сервере, тогда я SqlBulkCopy
в промежуточную таблицу и, наконец, запустите хранимую процедуру для перемещения таблицы из промежуточной таблицы в фактическую таблицу; преимущества:
- нет проблем с повреждением данных в реальном времени, если импорт не выполняется точка
- я могу поместить транзакцию только вокруг SPROC
- я могу иметь работу bcp без регистрации, безопасно зная, что SPROC будет зарегистрирован
- это просто ; - p (не возиться с отображениями)
в качестве последней мысли-если вы имеете дело с объемными данными, вы можете получить лучшую пропускную способность, используя IDataReader
(так как это потоковый API, где-as DataTable
является буферизованным API). Например, я склонен подключать импорт CSV с помощью CsvReader в качестве источника для SqlBulkCopy. Кроме того, я написал обертки вокруг XmlReader
чтобы представить каждый элемент первого уровня в виде строки в IDataReader
- очень быстро.
Я столкнулся с той же проблемой при копировании данных из access в SQLSERVER 2005, и я обнаружил, что сопоставления столбцов чувствительны к регистру в обоих источниках данных независимо от чувствительности баз данных.
ответ марка будет моей рекомендацией (при использовании промежуточной таблицы). Это гарантирует, что если ваш источник не меняется, у вас будет меньше проблем с импортом в будущем.
однако, по моему опыту, вы можете проверить следующие проблемы:
имена столбцов совпадают в источнике и таблице Что типы столбцов соответствуют
Если вы думаете, что вы это сделали и до сих пор не добились успеха. Вы можете попробовать следующее.
1-разрешить нули во всех столбцах таблица 2-прокомментируйте все сопоставления столбцов 3-повторите добавление одного столбца за раз, пока не найдете, где ваша проблема
Это должно вывести ошибку
одна из причин заключается в том, что :SqlBukCOpy чувствителен к регистру . Выполните следующие действия:
- в этом случае сначала вы должны найти свой столбец в исходной таблице по использование метода "Contain" в C#.
- как только ваш столбец назначения соответствует исходному столбцу, получите индекс этот столбец и дать его имя столбца в SqlBukCOpy .
Например:`
//Get Column from Source table
string sourceTableQuery = "Select top 1 * from sourceTable";
DataTable dtSource=SQLHelper.SqlHelper.ExecuteDataset(transaction, CommandType.Text, sourceTableQuery).Tables[0];// i use sql helper for executing query you can use corde sw
for (int i = 0; i < destinationTable.Columns.Count; i++)
{ //check if destination Column Exists in Source table
if (dtSource.Columns.Contains(destinationTable.Columns[i].ToString()))//contain method is not case sensitive
{
int sourceColumnIndex = dtSource.Columns.IndexOf(destinationTable.Columns[i].ToString());//Once column matched get its index
bulkCopy.ColumnMappings.Add(dtSource.Columns[sourceColumnIndex].ToString(), dtSource.Columns[sourceColumnIndex].ToString());//give coluns name of source table rather then destination table so that it would avoid case sensitivity
}
}
bulkCopy.WriteToServer(destinationTable);
bulkCopy.Close();
Я обнаружил, что столбцы в таблице и столбцы во входных данных должны по крайней мере совпадать. Вы можете иметь несколько столбцов в таблице, и вход будет по-прежнему нагрузки. Если у вас меньше, вы получите ошибку.
долго думал над ответом... Даже если имена столбцов имеют одинаковый регистр, если тип данных отличается вы получаете ту же ошибку. Поэтому проверьте имена столбцов и их тип данных.
С. П.: промежуточные таблицы являются окончательными путь для импорта.
Я бы пошел с идеей постановки, однако вот мой подход к обработке чувствительного к регистру характера. Счастлив быть критикуемым на моем linq
using (SqlConnection connection = new SqlConnection(conn_str))
{
connection.Open();
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
{
bulkCopy.DestinationTableName = string.Format("[{0}].[{1}].[{2}]", targetDatabase, targetSchema, targetTable);
var targetColumsAvailable = GetSchema(conn_str, targetTable).ToArray();
foreach (var column in dt.Columns)
{
if (targetColumsAvailable.Select(x => x.ToUpper()).Contains(column.ToString().ToUpper()))
{
var tc = targetColumsAvailable.Single(x => String.Equals(x, column.ToString(), StringComparison.CurrentCultureIgnoreCase));
bulkCopy.ColumnMappings.Add(column.ToString(), tc);
}
}
// Write from the source to the destination.
bulkCopy.WriteToServer(dt);
bulkCopy.Close();
}
}
и вспомогательный метод
private static IEnumerable<string> GetSchema(string connectionString, string tableName)
{
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = "sp_Columns";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@table_name", SqlDbType.NVarChar, 384).Value = tableName;
connection.Open();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
yield return (string)reader["column_name"];
}
}
}
}