sankarisiva Ответов: 3

Эффективный способ загрузки огромных данных в datatable


Привет, я загружаю файл DBF в существующую таблицу sql в консольном приложении c#. Во-первых ,мой dbf-файл,содержащий 8,50,000+ записей, я должен был загрузить весь DBF-файл в datatable, это привело к исключению нехватки памяти при обработке 400000+ записей. Поэтому я читаю запись за раз и добавляю в datatable в виде строки. Он прекрасно работал до 6,00 000 + записей. После этой записи я столкнулся с системой.OutofMemoryException. Пожалуйста, кто-нибудь помогите мне загрузить файл DBF в таблицу sql в консольном приложении c#. Мой код здесь, я пробовал много оптимизаций кода, но безрезультатно
 public void ConvertDBFtoSQL() {
     string connStr = @"Provider=VFPOLEDB.1;Data Source=dbf file path;Persist              Security Info=False; User ID=Admin;Password=;";
     using (OleDbConnection oleDbConnection = new OleDbConnection(connStr))
     {
         oleDbConnection.Open();
         string query = "select * from dbftable";
         OleDbCommand oleDbCommand = new OleDbCommand(query, oleDbConnection);
         oleDbCommand.CommandTimeout = 600000;
         OleDbDataReader oleDbDataReader = oleDbCommand.ExecuteReader();
         int fieldCount = oleDbDataReader.FieldCount;
         DataTable dataTable= CreateDataTable();
         string[] rows = new string[fieldCount];
         while (oleDbDataReader.Read())
         {                     
             using (dataTable)
             {
                 Array.Clear(rows, 0, rows.Length);
                 for (int i = 0; i < fieldCount; i++)
                 {
                     try
                     {
      rows[i] = oleDbDataReader.GetFieldType(i).Name.ToLower() == "datetime"?
"\"" + Convert.ToDateTime(oleDbDataReader.GetValue(i)).ToString("dd/MM/yyyy").Substring(0, 10) + "\"":
                         
                             (oleDbDataReader.GetValue(i).ToString().Contains(",") ? "" :"\"" + oleDbDataReader.GetValue(i).ToString().Trim() + "\"");                                 
                     }
                     catch (Exception ex) { }
                 }
                 string row = string.Join(",", rows);
                 dataTable.Rows.Add(new object[] { row });
             }
         }
     }
}


Что я уже пробовал:

Сначала я попробовал dataTable.Load (oledbcommand.executereader()) это сбой с исключением из памяти, тогда я попробовал прочитать строку и добавить в datatable.

Michael_Davies

Зачем вы их все загружаете? Никто не может прочесть их все или увидеть их все!

Tomas Takac

Данные просто слишком велики, вы не можете загрузить их все в память. Зачем вам это нужно в первую очередь?

sankarisiva

Потому что мне нужно загрузить все эти данные в таблицу sql. Если у i datatable есть целые данные, то я могу использовать опцию bulkinsert для загрузки в таблицу sql

Tomas Takac

Нет, вам не нужно загружать все это в память. SqlBulkCopy может использовать считыватель данных.[^]

3 Ответов

Рейтинг:
22

Tomas Takac

Вы можете использовать средство чтения данных с помощью SqlBulkCopy:

const string sourceConnectionString = "abc";
const string targetConnectionString = "xyz";

using (var sourceConnection = new OleDbConnection(sourceConnectionString))
using (var targetConnection = new SqlConnection(targetConnectionString))
using (var sourceCommand = new OleDbCommand("select * from dbftable", sourceConnection))
{
	sourceConnection.Open();
	targetConnection.Open();
	
	using (var reader = sourceCommand.ExecuteReader())
	using (var bulkCopy = new SqlBulkCopy(targetConnection))
	{
		bulkCopy.DestinationTableName = "aTableName";
		bulkCopy.BatchSize = 1000;
		bulkCopy.WriteToServer(reader);
	}
}


sankarisiva

Извините за задержку и спасибо за ваш ответ. Я пробовал этот метод, но он создает исключение тайм-аута, и никакие записи не вставляются в целевую таблицу.

F-ES Sitecore

Просто обрабатывайте данные кусками по тысяче или что-то еще, а не все сразу. Если вам нужно было переместить 10 валунов из А В В, и вы недостаточно сильны, чтобы нести их все сразу, вы должны делать это по 1 за раз, здесь та же концепция.

Tomas Takac

Как сказал F-ES, установите размер пакета на соответствующее значение. См. Мой редактировать.

sankarisiva

Спасибо. Этот метод отлично работает

Рейтинг:
19

Mehdi Gholam

Прочитать следующее : foxpro-как импортировать файл DBF в SQL Server-Stack Overflow[^]


sankarisiva

У меня уже есть эти методы, которые производят исключение как синтаксическую ошибку

Mehdi Gholam

1) Выберите меньше данных с помощью фильтра и делайте это кусками
2) запуск на 64-битной системе.

sankarisiva

Я работаю на 86bit

Mehdi Gholam

86бит??

sankarisiva

Я установил свою платформу сборки как x86. Тогда только я мог бы файл dbf

Mehdi Gholam

Затем отфильтруйте свои данные и импортируйте их логическими блоками.

sankarisiva

Вы говорите, как вставить в таблицу sql куски записей dbf. я прав?

Mehdi Gholam

"выберите * из dbftable where ..." - & gt; заполните часть where.

sankarisiva

Я думаю, что в моей ситуации фильтрация данных невозможна. Мне нужно загрузить все эти данные, доступные в файле dbf. Можете ли вы предложить мне другое решение?

Mehdi Gholam

А почему бы и нет? фильтруйте свои данные, чтобы сделать их меньше, и меняйте фильтр до тех пор, пока не охватите все строки.

sankarisiva

Извини, что не могу уловить твою мысль. У меня есть столбцы типа a,b,c, d,... всего 74 столбца и 850000+ записей, Как я могу это отфильтровать. Нет никаких ограничений с данными

Mehdi Gholam

Попробуйте добавить номер строки и отфильтровать его.

sankarisiva

- Вы правы. Но я не могу изменить исходный файл dbf.Вот с какой проблемой я столкнулся

sankarisiva

Благодаря этому методу прекрасно работает Мехди голам...