2012-10-31 6 views
1

Имейте веб-форму, в которой есть кнопка загрузки для загрузки файла csv, тогда мой код должен проанализировать файл и использовать проанализированные данные для вставки в таблицу SQL. Это то, что я делаю правильно для данных синтаксического анализа в List, это не подбирает имя файла для streamreader. Является ли это наиболее эффективным способом анализа данных? Должен ли я анализировать данные?Загрузить файл csv, проанализировать, затем перевести данные в таблицу SQL

protected void UploadBtn_Click(object sender, EventArgs e) 
{ 
    if (FileUpload.HasFile) 
    { 

     string filename = Path.GetFileName(FileUpload.FileName); 
     List<string[]> ValuesToUpload = parseData(filename); 

     //if (!Directory.Exists(ConfigurationManager.AppSettings["temp_dir"].ToString().Trim())) 
     //{ 
     // Directory.CreateDirectory(ConfigurationManager.AppSettings["temp_dir"].ToString().Trim()); 
     //} 
     //FileUpload.SaveAs(ConfigurationManager.AppSettings["temp_dir"].ToString().Trim() + filename); 
     //using (FileStream stream = new FileStream(ConfigurationManager.AppSettings["temp_dir"].ToString().Trim() + filename, FileMode.Open, FileAccess.Read, FileShare.Read)) 
    } 
} 
     public List<string[]> parseData(filename) 
      { 
      int j=0; 
      List <string[]> members = new List<string[]>(); 
      try 
      { 
       using (StreamReader read = new StreamReader(filename)) 
       { 
        while (!read.EndOfStream) 
        { 
         string line = read.ReadLine(); 
         string[] values = line.Split(','); 
         if(j==0) 
         { 
          j++; 
          continue; 
         } 

         long memnbr = Convert.ToInt64(values[0]); 
         int loannbr = Convert.ToInt32(values[1]); 
         int propval = Convert.ToInt32(values[2]); 
         members.Add(values); 
        } 
+0

CsvReader от codeproject? –

+0

Кажется довольно эффективным для меня, по крайней мере, в отношении производительности, может быть, не с точки зрения строк кода, но я лично склонен это делать. Я не собираюсь добавлять зависимость (например, предложенную выше), если она не будет широко использоваться во всем приложении. – evanmcdonnal

+0

Если много данных, вы можете сделать массовую вставку в промежуточную таблицу, а затем выполнить хранимую процедуру для анализа/номизации данных в фактических таблицах. – Dennis

ответ

0

Поскольку вы собираетесь вставить данные в таблицу SQL, я бы сначала создать класс, который представляет таблицу и создать новый объект для каждой записи. (это для видимости).

или я мог бы использовать следующие подходы (если вы используете MS SQL Server) 1. Динамический Insert Query

StringBuilder strInsertValues = new StringBuilder("VALUES"); 

your ParsingCode HERE.. 
string [] values = line.Split(','); 
strInsertValues.AppendFormat("({0},{1},{2}),", values[0], values[1], values[2]); 

end parse 


using(SqlConnection cn = new SqlConnection(YOUR_CONNECTION_STRING)){ 
    SqlCommand cmd = cn.CreateCommand; 
    cmd.CommandType = SqlCommandType.Text; 
    cmd.CommandText = "INSERT INTO TABLE(Column1, Column2, Column3) " + strInsertValues.ToString().SubString(0, strInsertValues.Length); 
    cn.Open(); 
    cmd.ExecuteNonQuery(); 

} 

2. Использование BulkCopy (Рекоммендуемый) Создание набора данных представляет из вашей CSV значения Добавить новую запись для каждой анализируемой строки Создание сопоставлений столбцов для вашей таблицы DataSet и SQL, Используйте объект BulkCopy для вставки ваших данных. Ссылка на BulkCopy: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx

0

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

Как это выглядит, как вы выбрасывая свои разобранные значения (memnbr и т.д ...) , вы можете значительно уменьшить Csv код разбора:

return 
File 
    .ReadLines(filename) 
    .Skip(1) 
    .Select(line => line.Split(',')) 
    .ToList(); 
1

Использование KBCsv. Мы получаем 40K строк, анализируемых в секунду, а строки 70K + пропускаются в секунду. Это самое быстрое, что я видел. А также довольно стабильно. Затем создайте SQL вручную, как было предложено выше. Если вы выполняете перезагрузку данных и нацелены на производительность, запустите многопоточную транзакцию (только для MS SQL). Может получать до 10 тыс. Строк в секунду скорости импорта, в зависимости от пропускной способности сети до сервера базы данных.

Не разбирайте команду DataTable - это очень медленно.

+0

+1. Спасибо за ссылку на KBCsv. Я обязательно буду использовать эту библиотеку в следующий раз, когда мне нужно будет написать/разглядеть большой файл CSV. – Dennis

0

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

Это значительно эффективнее, чем ручной анализ данных и вставка данных по строкам. Несколько месяцев назад я использовал аналогичный код, чтобы отправить 150000 записей в нашу базу данных и нормализовать данные за считанные секунды.

var sqlConnection = new SqlConnection(DbConnectionStringInternal); 

// Bulk-import our unnormalized data from the .csv file into a staging table 
var inputFileConnectionString = String.Format("Driver={{Microsoft Text Driver (*.txt; *.csv)}};Extensions=csv;Readonly=True;Dbq={0}", Path.GetDirectoryName(csvFilePath)); 
using (var inputFileConnection = new OdbcConnection(inputFileConnectionString)) 
{ 
    inputFileConnection.Open(); 

    var selectCommandText = String.Format("SELECT * FROM {0}", Path.GetFileName(csvFilePath)); 
    var selectCommand = new OdbcCommand(selectCommandText, inputFileConnection); 
    var inputDataReader = selectCommand.ExecuteReader(CommandBehavior.CloseConnection); 

    var sqlBulkCopy = new SqlBulkCopy(sqlConnection) { DestinationTableName = "Data_Staging" };  
    if (sqlConnection.State != ConnectionState.Open) 
     sqlConnection.Open(); 

    sqlBulkCopy.WriteToServer(inputDataReader);  
} 

// Run a stored-procedure to normalize the data in the staging table, then efficiently move it across to the "real" tables. 
var addDataFromStagingTable = String.Format("EXEC SP_AddDataFromStagingTable"); 
if (sqlConnection.State != ConnectionState.Open) 
    sqlConnection.Open(); 

using (var addToStagingTableCommand = new SqlCommand(addDataFromStagingTable, sqlConnection) { CommandTimeout = 60 * 20 }) 
    addToStagingTableCommand.ExecuteNonQuery();  

sqlConnection.Close(); 
Смежные вопросы