将SqlDataReader结果导出到C#中的数组

时间:2016-12-09 20:53:23

标签: c# excel sqlite sqldatareader excel-dna

我编写了一个运行SQL查询的函数,并使用ExcelDNA将其公开给Excel。查询本身使用SqlDataAdapter及其相应的.Fill()方法填充DataTable

然后我遍历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

2 个答案:

答案 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