1DSparrows Ответов: 2

Как разделить большую таблицу данных на несколько таблиц данных, работающих на VS2005


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

Теперь я создаю условие в своем модуле, что если rows.count больше 100 000, то он будет циклически зависеть от моего условия.

Я разделил rows.count на 30000, потому что предполагаю, что самый большой файл, который я загружу, будет иметь количество 150 000.

с должно быть целое число, так что причина, по которой я всегда ставлю + 1, Если с это не целое число.

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

Спасибо Вам за помощь.

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

If (dt.Rows.Count > 100000) Then

Dim Columns As DataRow = dt.NewRow
Dim c = dt.Rows.Count / 30000
Dim SNumber = Convert.ToInt64(System.Math.Ceiling(c))

dt.Columns.Add("Key_Id", GetType(String))

If c = CDbl(c) Then
c = System.Math.Floor(c + 1)

Dim dtArr(c) As DataTable
For j As Integer = 0 To c

dtArr(j) = dt.Select("Key_Id <= 1 And Key_Id >= 30000").Clone()
dtArr(j) = dt.Select("Key_Id <= 30001 And Key_Id >= 60000").Clone()
dtArr(j) = dt.Select("Key_Id <= 60001 And Key_Id >= 90000").Clone()
dtArr(j) = dt.Select("Key_Id <= 90001 And Key_Id >= 120000").Clone()
dtArr(j) = dt.Select("Key_Id <= 120001 And Key_Id >= 150000").Clone()

Next

End If

End If

Jαved

похоже, ваш код ошибочен. переменная "dtArr" имеет тип "double".
т. е. Dim dtArr = _New_dt.Rows.Количество / 30000

1DSparrows

dtArr имеет возможность быть десятичным,

Jαved

нет, именно десятичный код не будет работать и выдаст ошибку.

1DSparrows

так что dtArr-это единственная ошибка в моем кодировании?

Jαved

Да, объявить еще одну переменную, чтобы установить счетчик, чтобы разделить и объявить dtArr чтобы быть DataTable массив - Дим dtArr() в качестве объекта DataTable и в петлю массив как-
dtArr(i) = dt.Select("key_id <= 1 и key_id >= 30000").Copytodatable()

1DSparrows

Dim _New_dt Как Новый DataTable()

_New_dt = ДТ


ДТ.колонны.Add("Key_Id", GetType(String))

Dim c = _New_dt.Rows.Количество / 30000
Dim SheetNumber = Преобразовать.ToInt64(Матем.Потолок(c))
Если c = CDbl(c), то
с = Математика.Этаж(с + 1)

Dim dtArr(c) как DataTable

dtArr(c) = dt.Select("key_id <= 1 и key_id >= 30000").Клон()
dtArr(c) = dt.Select("key_id <= 61000 и key_id >= 90000").Клон()
dtArr(c) = dt.Select("key_id <= 91000 и key_id >= 120000").Клон()
dtArr(c) = dt.Select("key_id <= 121000 и key_id >= 150000").Клон()

1DSparrows

Я придумал эту кодовую базу по вашему предложению, но столкнулся с ошибкой. Невозможно привести объект типа "System.Data.DataTable" к типу "myStronglyTypedDataTable"

Jαved

используйте приведенный ниже код-

Dim _New_dt Как Новый DataTable()

_New_dt = ДТ

ДТ.колонны.Add("Key_Id", GetType(String))

Dim c = _New_dt.Rows.Количество / 30000
Dim SheetNumber = Преобразовать.ToInt64(System.Math.Потолок(c))
'Если c = CDbl(c), то
'с = Система.Математика.Этаж(с + 1)

Dim dtArr(c) как DataTable
Для j = 0 - c
dtArr(j) = dt.Select("key_id <= 1 и key_id >= 30000").Copytodatable()
dtArr(j) = dt.Select("key_id <= 61000 и key_id >= 90000").Copytodatable()
dtArr(j) = dt.Select("key_id <= 91000 и key_id >= 120000").Copytodatable()
dtArr(j) = dt.Select("key_id <= 121000 и key_id >= 150000").Copytodatable()
Следующий

-Конец, Если

1DSparrows

CopyToDataTable не является членом системного массива

1DSparrows

Я использовал ваш код, но все еще получаю ошибку, неспособную привести объект типа " System.Data.DataRow[]" к типу "System.Data.DataTable", а CopyToDataTable не является членом системного массива.

2 Ответов

Рейтинг:
2

1DSparrows

@javed я уже прошел по этой ссылке, но еще не исправил свой код на нужной.

Jαved

в чем проблема с решениями, приведенными в ссылке?

1DSparrows

Дим таблицы в виде списка(объект DataTable) = новый список(из объекта DataTable)()
Dim batchSize как целое число
Dim c как целое число = 0
Dim j как целое число = 1
Dim rowCount As Integer = 0
Dim tempDt As DataTable = dt.Clone()
tempDt.Имятаблицы = "scm_move_order" &амп; Дж.Метод toString()
tempDt.Понятно()
Для каждой из строк datarow в ДТ.Строк
количество строк += 1
Дим невров в качестве объекта datarow = tempDt.Невров()
невров.ItemArray = строка.ItemArray
tempDt.Строк.Добавить(невров)
c += 1
Если c = batchSize или rowCount = dt.Rows.Тогда Считай
таблицы.Добавить(tempDt)
j += 1
tempDt = dt.Clone()
tempDt.Имятаблицы = "scm_move_order" &амп; Дж.Метод toString()
tempDt.Понятно()
c = 0
Конец, Если
Следующий

1DSparrows

Я следовал этому коду, но все равно получил ошибку out of memory

Jαved

вы перебираете все строки в главной таблице "dt" не обязательно, и проверка размера пакета находится в середине цикла, это должна быть первая проверка в цикле.
Хотя этот код займет много времени и не оптимизирован.

Maciej Los

5ed!

1DSparrows

Что?

Maciej Los

Взгляните на верхний правый угол решения. Она называется: система голосования.

1DSparrows

Ой.ладно

Рейтинг:
2

Maciej Los

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

dtArr() = dt.Select("key_id <= 1 And key_id >= 30000").Clone()
dtArr() = dt.Select("key_id <= 31000 And key_id >= 60000").Clone()
dtArr() = dt.Select("key_id <= 61000 And key_id >= 90000").Clone()
dtArr() = dt.Select("key_id <= 91000 And key_id >= 120000").Clone()
dtArr() = dt.Select("key_id <= 121000 And key_id >= 150000").Clone()


Вы смешали less than и greater than операторы! Другая проблема заключается в том, что вы теряете 1000 записей (31000-3000=1000) между каждой из них. select!

Если вы хотите разделить данные на части с 30000 записями, вы можете использовать Linq. Взгляните на пример...

Способ № 1 - копирование данных с помощью key_id:



//source table
DataTable src = new DataTable();
src.Columns.Add(new DataColumn("key_id", typeof(int)));
//add example data
src = Enumerable.Range(1,100).Select(x=>src.LoadDataRow(new object[]{x}, false)).CopyToDataTable();

int increasement = 30;
int curVal = 1;
//temporary object type of datarow
DataRow[] result = null;
//destination dataset, here we'll store smaller datatables
DataSet ds = new DataSet();
do
{
	result = src.AsEnumerable()
		.Where(x=>x.Field<int>("key_id")>=curVal && x.Field<int>("key_id")<curVal+increasement)
		.ToArray();
	if(result.Length>0)
	{
		DataTable tmp = src.Clone();
		tmp = result.CopyToDataTable();
		ds.Tables.Add(tmp);
	}
	curVal+=increasement;
} while(result.Length>0);

Dim src As DataTable = New DataTable()
src.Columns.Add(New DataColumn("key_id", Type.GetType("System.Int32")))
'add example data
src = Enumerable.Range(1,100).Select(Function(x) src.LoadDataRow(New Object(){x}, False)).CopyToDataTable()

Dim increasement As Integer = 30
Dim curVal As Integer = 1
Dim result As DataRow()
Dim ds As DataSet = New DataSet()
Do 
	result = src.AsEnumerable() _
		.Where(Function(x) x.Field(Of Integer)("key_id")>=curVal And x.Field(Of Integer)("key_id")<curVal+increasement) _
		.ToArray()
	If result.Length>0 Then
		Dim tmp As DataTable = src.Clone()
		tmp = result.CopyToDataTable()
		ds.Tables.Add(tmp)
	End If
	curVal+=increasement
Loop While(result.Length>0)



Способ № 2 - копирование одного и того же количества строк:



int increasement = 30;
int curVal = 0; //start with 0!
DataRow[] result = null;
DataSet ds = new DataSet();
do
{
	result = src.AsEnumerable()
		.Skip(curVal) //
		.Take(increasement)
		.ToArray();
	if(result.Length>0)
	{
		DataTable tmp = src.Clone();
		tmp = result.CopyToDataTable();
		ds.Tables.Add(tmp);
	}
	curVal+=increasement;
} while(result.Length>0);


Dim increasement As Integer = 30
Dim curVal As Integer = 0
Dim result As DataRow()= Nothing
Dim ds As DataSet = New DataSet()
Do 
	result = src.AsEnumerable() _
		.Skip(curVal) _
		.Take(increasement) _
		.ToArray()
	If result.Length>0 Then
		Dim tmp As DataTable = src.Clone()
		tmp = result.CopyToDataTable()
		ds.Tables.Add(tmp)
	End If
	curVal+=increasement
Loop While(result.Length>0)




[РЕДАКТИРОВАТЬ]
Non-Linq решение - метод #1:

'needed:
'Imports System.Data
'Imports System.Text

Dim src As DataTable = New DataTable()
src.Columns.Add(New DataColumn("key_id", Type.GetType("System.Int32")))
'add example data
For i As Integer = 0 To 100
    src.Rows.Add(New Object() {i})
Next

Dim increasement As Integer = 30
Dim curVal As Integer = 1
Dim result As DataRow()
Dim ds As DataSet = New DataSet()
Do
    result = src.Select(String.Format("key_id >={0} And key_id<{1}", curVal, curVal + increasement)).Clone()
    If result.Length > 0 Then
        Dim tmp As DataTable = src.Clone()
        Dim sb As StringBuilder = New StringBuilder()
        For Each dr As DataRow In result
            tmp.Rows.Add(New Object() {dr("key_id")})
            sb.Append(String.Format("{0};", dr("key_id")))
        Next
        ds.Tables.Add(tmp)
        Console.WriteLine("{0}", sb.ToString())
        sb = Nothing
    End If
    curVal += increasement
Loop While (result.Length > 0)

Console.ReadKey()


Результат (4 таблицы):
1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;
31;32;33;34;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52;53;54;55;56;57;58;59;60;
61;62;63;64;65;66;67;68;69;70;71;72;73;74;75;76;77;78;79;80;81;82;83;84;85;86;87;88;89;90;
91;92;93;94;95;96;97;98;99;100;


[КОНЕЦ РЕДАКТИРОВАНИЯ]

Удачи вам!


1DSparrows

Я использовал ваш код выше, но методом asenumerable' не является членом 'системы.Данных.Объект DataTable. Я добавляю ссылку, но все равно получаю ошибку. Оба метода не работают. Я использую Visual Studio 2005.

Maciej Los

Вы не упомянули о VS 2005. Да, для VS2005 это не сработает. Я постараюсь найти способ обойтись без Linq.

1DSparrows

Прости, что не упомянул об этом. Я работаю в VS2005.

Maciej Los

Готово! Проверьте мой ответ.

1DSparrows

всегда ли увеличение как целое число = 30, или я могу изменить его на основе диапазона, который мне нужен, чтобы таблица могла иметь? значит, если я поставлю 30000, то в таблице будет каждый 30000?

Maciej Los

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

1DSparrows

Привет, я все еще получаю ошибку out of memory, когда загружаю 130 000 записей.

Maciej Los

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

1DSparrows

Код был правильным, но проблема в том, что цикл просто продолжался, и ничего не происходило. Я даже не успел успешно загрузить эти данные в свою базу данных. Таким образом, console.readkey() предназначен для консольного приложения? Я делаю веб-приложение в ASP.NET приложение (например, работающее в IIS).

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

1DSparrows

Вот как я использовал ваш код:

Если (ДТ.Строк.Граф > 100000) Затем

Дим Scr как объект DataTable = новый объект DataTable()
scr.колонки.Add(New DataColumn("key_id", Type.Метод Gettype (Системы".Типа int32")))

Для _c как целого числа = 0 до dt.строк.Рассчитывать
scr.Rows.Add(New Object() {_c})
Следующий

Дим организма как целого = 30000
Dim curVal As Integer = 1
Тусклый результат как DataRow()
Dim ds As DataSet = новый набор данных()
Делать
результат = ОПЗ.Выберите(Строка.Формат("key_id >={0} и key_id<{1}", curVal, curVal + increasement)).Клон()
Если результат.Длина > 0 затем
Dim tmp As DataTable = scr.Клон()
Dim sb As StringBuilder = новый StringBuilder()
Для каждого dr As DataRow в результате
tmp.Rows.Add(New Object() {dr("key_id")})
sb.Append(строка.Формат("{0};", dr("key_id")))
Следующий
ДС.столы.Добавить(tmp)
Приставка.WriteLine("{0}", sb.ToString())
sb = ничего
Конец, Если
кривизна += увеличение
Цикл While (результат.Длина > 0)


Конец, Если

ДТ.Метода writexml(писатель, ложные)