Загрузка CSV на SQL Server - PullRequest
       3

Загрузка CSV на SQL Server

3 голосов
/ 03 сентября 2011

Я строю систему, которая читает 5 CSV-файлов каждый месяц.Эти файлы должны соответствовать определенному формату и порядку.У меня есть одна главная таблица и 5 временных таблиц.Каждый CSV-файл сначала читается, а затем массово вставляется в соответствующую временную таблицу.После массовой вставки 5 CSV-файлов в соответствующие временные таблицы я снова вставляю все записи из временной таблицы в основную таблицу.Это гарантирует, что все файлы загружаются в первую очередь перед вставкой данных в основную таблицу.

Я построил эту систему с использованием ASP.net, и во время отладки и тестирования все прошло нормально.Проблема возникает всякий раз, когда я развертываю приложение на производственном сервере.После развертывания приложения я использовал те же CSV-файлы, которые я загружал во время разработки и тестирования, и система показывает ошибку преобразования данных из формата строки в дату и время.

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

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

Интересно, сталкивался ли кто-нибудь с этим?аналогичная проблема во время развертывания.Мне все еще кажется странным, что поведение приложения изменилось после развертывания.

Ниже приведен фрагмент кода, в который оно загружает файл inventory.csv на сервер и затем массово вставляет файл csv во временную таблицу.Затем TB_TEMP_INVENTORY вставляет записи из temp в основную таблицу TB_CATTLE.это сделано для 4 других файлов и почти идентично этому.

        OleDbConnection conn = new     OleDbConnection(ConfigurationManager.AppSettings["LivestockConnectionString"]);
        OleDbCommand comm;
        OleDbDataAdapter adapter;
        DataTable table = new DataTable();
        string file = string.Empty;
        string content = string.Empty;
        StreamReader reader;
        StreamWriter writer;
        string month = monthDropDownList.SelectedValue;
        string year = yearDropDownList.SelectedItem.Text;

        // upload inventory file
        file = System.IO.Path.GetFileName(inventoryFileUpload.PostedFile.FileName);
        inventoryFileUpload.PostedFile.SaveAs("C://LivestockCSV//" + file);

        // clean inventory file
        file = "C://LivestockCSV//" + file;
        reader = new StreamReader(file);
        content = reader.ReadToEnd();
        reader.Close();
        writer = new StreamWriter(file);
        writer.Write(content.Replace("\"", ""));        // remove quotation
        writer.Close();
        writer = new StreamWriter(file);
        writer.Write(content.Replace(",NULL,", ",,"));  // remove NULL
        writer.Close();
        writer = new StreamWriter(file);
        writer.Write(content.Replace(",0,", ",,"));     // remove 0 dates
        writer.Close();
        writer = new StreamWriter(file);
        writer.Write(content.Replace(",0", ","));       // remove 0 dates at eol
        writer.Close();

        try
        {
            conn.Open();
            comm = new OleDbCommand("TRUNCATE TABLE TB_TEMP_INVENTORY", conn);    // clear temp table
            comm.ExecuteNonQuery();

            // bulk insert from csv to temp table
            comm = new OleDbCommand(@"SET DATEFORMAT DMY;
                                    BULK INSERT TB_TEMP_INVENTORY
                                    FROM '" + file + "'" +
                                    @" WITH
                                    (
                                        FIELDTERMINATOR = ',',
                                        ROWTERMINATOR = '\n'
                                    )", conn);
            comm.ExecuteNonQuery();

            // check if data for same month exists in cattle table
            comm = new OleDbCommand(@"SELECT *
                                    FROM TB_CATTLE
                                    WHERE Report='Inventory' AND Month=" + month + " AND Year=" + year, conn);

            if (comm.ExecuteScalar() != null)
            {
                comm = new OleDbCommand(@"DELETE
                                        FROM TB_CATTLE
                                        WHERE Report='Inventory' AND Month=" + month + " AND Year=" + year, conn);
                comm.ExecuteNonQuery();
            }


            // insert into master cattle table
            comm = new OleDbCommand(@"SET DATEFORMAT MDY;
                                    INSERT INTO TB_CATTLE(ID, Sex, BirthDate, FirstCalveDate, CurrentUnit, OriginalCost, AccumulatedDepreciation, WrittenDownValue, NetRealizableValue, CapitalGainLoss, Month, Year, Report, Locked, UploadedBy, UploadedAt)
                                    SELECT DISTINCT ID, Sex, BirthDate, FirstCalveDate, CurrentUnit, 0, 0, 0, 0, 0, " + month + ", " + year + @", 'Inventory', 0, 'Admin', '" + DateTime.Now + @"'
                                    FROM TB_TEMP_INVENTORY", conn);
            comm.ExecuteNonQuery();
            conn.Close();
        }
        catch (Exception ex)
        {
            ClientScript.RegisterStartupScript(typeof(string), "key", "<script>alert('" + ex.Message + "');</script>");
            return;
        }

Ответы [ 2 ]

2 голосов
/ 03 сентября 2011

1) Проверьте параметры SQL Server LANGUAGE и DATEFORMAT для dev / testing & production env.:

DBCC USEROPTIONS

2) Какой формат даты используется в файлах CSV (источник)?

3) Какой тип данных используется для поля даты / времени (пункт назначения)?

DECLARE @v VARCHAR(10) = '2010-08-23';

SET DATEFORMAT mdy;
SELECT CAST(@v AS DATETIME)
        ,CAST(@v AS DATE)
        ,YEAR(CAST(@v AS DATETIME))
        ,MONTH(CAST(@v AS DATETIME))
        ,DAY(CAST(@v AS DATETIME));

SET DATEFORMAT dmy;
SELECT CAST(@v AS DATETIME)
        ,CAST(@v AS DATE);
2 голосов
/ 03 сентября 2011

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

Другой вариант - использовать очень простую вставку в промежуточную таблицу и обрабатывать данные с помощью кода TSQL.

Почему это изменилось между dev / production; наиболее вероятные ответы:

  • данные, которые вы использовали в dev, не были репрезентативными
  • существует разница между средой / конфигурацией между этими
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...