Я написал функцию, которая выполняет SQL-запрос, и выставил ее в Excel с помощью ExcelDNA. Сам запрос использует SqlDataAdapter
и соответствующий ему метод .Fill()
для заполнения DataTable
.Экспорт результатов SqlDataReader в массив в C#
Я тогда перебирать строки и столбцы DataTable
для заполнения 2D массива, который определяется как,
object[,] results = new object[dt.Rows.Count, dt.Columns.Count];
можно затем непосредственно вернуть results
объект в Excel, и все отображается правильно (строки как строки и числа как значения).
Однако я столкнулся с проблемой, когда определенные SQL-запросы вызывают исключение «Out of Memory» при вызове метода .Fill()
.
Я провел небольшое исследование и выяснил, что SqlDataReader
может быть более эффективным, поскольку мне интересно только получать данные в Excel, и он не будет загружать результирующий набор в память, а скорее читать их подряд за строкой ,
Проблема у меня есть то, что нет .Fill()
метод для SqlDataReader
. У меня есть некоторый рабочий код, где я могу выводить результаты SQL как CSV-файл. Тогда, я полагаю, я мог бы написать еще одну функцию для импорта CSV в Excel. Но это кажется очень крутым.
Есть ли более простой способ достичь этого?
Полный след следа исключения приведен ниже.
System.Data.SQLite.SQLiteException (0x80004005): out of memory
out of memory
at System.Data.SQLite.SQLite3.Reset(SQLiteStatement stmt)
at System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt)
at System.Data.SQLite.SQLiteDataReader.NextResult()
at System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)
at System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.SQLite.SQLiteCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataTable dataTable)
at UtilXL.Utils.UtilsSQLite.RunQueryCSLite(String SQLStatement, String FilePath, Boolean IncludeHeaders) in h:\Projects\UtilXL\UtilXL\Utils\UtilsSQLite.cs:line 37
Строка 37 в ссылке, приведенной выше, является вызовом sda.Fill()
.
Это трассировки стека при выполнении SqlDataReader
,
System.Data.SQLite.SQLiteException (0x80004005): out of memory out of memory
at System.Data.SQLite.SQLite3.Reset(SQLiteStatement stmt)
at System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt)
at System.Data.SQLite.SQLiteDataReader.NextResult()
at System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)
at System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.SQLite.SQLiteCommand.ExecuteReader()
at UtilXL.Utils.UtilsSQLite.RunQueryCSReader(String SQLStatement, String FilePath, Boolean IncludeHeaders) in h:\Projects\UtilXL\UtilXL\Utils\UtilsSQLite.cs:line 111
Wouldn 't, что все будет проще, если вы вместо этого добавили данные в Excel через QueryTables.Add()? BTW это помечено как SQL-сервер, хотя это SQLite. –
Спасибо, исправил тег. Я не понимаю, почему заполнение самого DataTable является проблемой, если результатом запроса является всего несколько строк. Не те ли строки, которые отправляются в DataTable? Некоторые запросы, которые возвращают еще много строк (1000+), работают нормально. – insomniac
Где-то (может быть, в другом протекте), вы говорили 18 миллионов строк, а теперь несколько! Вероятно, «несколько» более реалистичны, DataTable вряд ли сможет справиться с такой нагрузкой. Я не видел ваш код и понятия не имею о ваших данных. –