SqlBulkCopy не работает - PullRequest
19 голосов
/ 13 января 2009

У меня есть DataSet, заполненный из листа Excel. Я хотел использовать SQLBulk Copy для вставки записей в таблицу Lead_Hdr, где LeadId - это PK.

У меня возникла следующая ошибка при выполнении кода ниже:

Данное 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 ]

39 голосов
/ 09 апреля 2010

Я столкнулся с той же проблемой при копировании данных из доступа к SQLSERVER 2005 и обнаружил, что сопоставления столбцов чувствительны к регистру в обоих источниках данных независимо от чувствительности баз данных.

22 голосов
/ 13 января 2009

Ну, правильно? Существуют ли имена столбцов с обеих сторон?

Если честно, я никогда не беспокоился о отображениях. Мне нравится быть проще: у меня обычно есть промежуточная таблица, которая выглядит как входные данные на сервере, затем я SqlBulkCopy в промежуточную таблицу и, наконец, запускаю хранимую процедуру, чтобы переместить таблицу из промежуточной таблицы в фактическую Таблица; Преимущества:

  • нет проблем с повреждением данных в реальном времени, если в любой момент произойдет сбой импорта
  • Я могу поставить транзакцию вокруг SPROC
  • Я могу заставить bcp работать без регистрации, безопасно зная, что SPROC будет зарегистрирован
  • это просто ;-p (не возиться с отображениями)

В заключение: если вы работаете с большими массивами данных, вы можете повысить пропускную способность, используя IDataReader (поскольку это потоковый API, где DataTable - это буферизованный API). Например, я склонен подключать импорт CSV, используя CsvReader в качестве источника для SqlBulkCopy. В качестве альтернативы я написал прокладки вокруг XmlReader, чтобы каждый элемент первого уровня представлял собой строку в IDataReader - очень быстро.

2 голосов
/ 19 августа 2016

Одной из причин является то, что: SqlBukCOpy чувствителен к регистру. Выполните шаги:

  1. В этом случае сначала вы должны найти свой столбец в таблице источников по используя метод «Contain» в C #.
  2. Как только ваш столбец Назначения сопоставлен с исходным столбцом, получите индекс этот столбец и укажите его имя в 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();
2 голосов
/ 14 января 2009

Ответом от Марка будет моя рекомендация (при использовании промежуточного стола). Это гарантирует, что если ваш источник не изменится, у вас будет меньше проблем с импортом в будущем.

Однако, по моему опыту, вы можете проверить следующие проблемы:

Имена столбцов совпадают в источнике и таблице Что типы столбцов совпадают

Если вы думаете, что сделали это, но все еще безуспешно. Вы можете попробовать следующее.

1 - разрешить пустые значения во всех столбцах таблицы 2 - закомментировать все сопоставления столбцов 3 - перезапустите добавление одного столбца за раз, пока вы не найдете, где ваша проблема

Это должно выявить ошибку

0 голосов
/ 09 октября 2017

Я бы пошел с идеей постановки, однако вот мой подход к обработке чувствительного к регистру характера. Рад, что меня критикуют на моем 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"];
                }
            }
        }
    }
0 голосов
/ 25 августа 2015

Долго думал об ответе ... Даже если имена столбцов одинаковы, если тип данных отличается Вы получаете ту же ошибку. Поэтому проверьте имена столбцов и их тип данных.

P.S .: промежуточные таблицы являются определяющим способом импорта.

0 голосов
/ 26 октября 2009

Я обнаружил, что столбцы в таблице и столбцы во входных данных должны как минимум совпадать. Вы можете иметь больше столбцов в таблице, и вход будет по-прежнему загружаться. Если у вас меньше, вы получите ошибку.

...