【发布时间】:2016-12-09 20:53:23
【问题描述】:
我编写了一个运行 SQL 查询的函数,并通过 ExcelDNA 将它暴露给 Excel。查询本身使用SqlDataAdapter 及其对应的.Fill() 方法来填充DataTable。
然后我遍历DataTable 的行和列以填充定义为的二维数组,
object[,] results = new object[dt.Rows.Count, dt.Columns.Count];
然后我可以直接将results 对象返回到 Excel,并且一切都正确呈现(字符串作为字符串,数字作为值)。
但是,我遇到了一个问题,即某些 SQL 查询在调用 .Fill() 方法时会引发“内存不足”异常。
我做了一些研究,结果发现SqlDataReader 可能更有效,因为我感兴趣的只是将数据检索到 Excel 中,它不会将结果集加载到内存中,而是将它们逐行读取行。
我的问题是SqlDataReader 没有.Fill() 方法。我确实有一些工作代码,可以在其中将 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
【问题讨论】:
-
如果您改为通过 QueryTables.Add() 将数据添加到 Excel,这不是更容易吗?顺便说一句,尽管它是 SQLite,但它被标记为 SQL 服务器。
-
谢谢,已更正标签。如果查询的结果只有几行,我不明白为什么填充 DataTable 本身就是一个问题。那些不是发送到 DataTable 的行吗?一些返回更多行(1000+)的查询工作得很好。
-
某处(可能在您的另一侧),您说的是 1800 万行,现在只有几行!可能“一些”更现实,DataTable 不太可能能够处理这样的负载。我没有看到你的代码,也不知道你的数据。
-
没有。 1800 万是整个数据库的大小。我正在运行的查询只返回 160 行。所以不知道为什么我会为这么小的结果集遇到 OOM 异常。
-
那真的很奇怪。从错误输出来看,它与 Excel 无关。它在加载到数据表时中断。您是否尝试过使用 Linq(您可以通过 Nuget 获得 IQToolkit)?
标签: c# excel sqlite sqldatareader excel-dna