我编写了一个运行SQL查询的函数,并使用ExcelDNA将其公开给Excel。查询本身使用SqlDataAdapter
及其相应的.Fill()
方法填充DataTable
。
然后我遍历DataTable
的行和列以填充定义为的
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
答案 0 :(得分:0)
我没有使用ExcelDNA的经验,但是......
我认为您应该尝试理解为什么要获得OutOfMemoryException
。它经常出现在使用大对象的32位应用程序中(在您的情况下,可能是字符串)。
确实,使用SqlDataReader
一次处理一行将在托管堆中使用比将所有行加载到DataTable
中更少的内存。但是,您需要一次将一行加载到Excel中 - 例如来自声明为:
object[,] results = new object[1, reader.FieldCount];
这可能比在一次调用中加载二维数组要慢。
答案 1 :(得分:0)
我认为这不是一个答案,但我不知道如何格式化代码。从你的另一个角度抓住你的基本代码,假设你从nuget获得IQToolkit,你能尝试这样的事情:
int numRows = data.Count() + (IncludeHeaders ? 1 : 0);
object[,] ret = new object[numRows, 3];
// ..
}
//// Entity Class
public class MyTable
{
public string CompanyName { get; set; }
public decimal Amount { get; set; }
public DateTime? Date { get; set; } // varchar, really?
public string AggCode { get; set; }
public string Level1 { get; set; }
//...
public string Level5 { get; set; }
// ...
public string Level20 { get; set; }
}
//如果成功到达这里,那么你状态良好
char