目前我正在使用的应用程序使用强类型DataSet
来处理来自数据库的数据。我们有一个名为COM_ControlIn
的表,代表一个"文件"和其他几个表与控制表有关系。我需要流式传输的是COM_GenericTransactionItems
。这个表中有一个名为COMControlIn_UID
的列,它根据名称将其链接到控制表。
我们有几种方法可以从这个表中获取数据,例如查找给定COMControlIn_UID
的所有记录的方法,但所有这些的问题是它们一次获取所有记录,这将成为一个现在问题是,大量的数据导致我们达到.NET的内存限制。我们所有的现有代码都使用由Visual Studio从数据库模式生成的XSD构建的强类型数据集。
我的想法是使用IEnumerable
来"流"来自数据库的批量记录,而不是一次性获取所有内容,同时仍保留我们之前使用的强类型数据集,以保持其兼容而不进行重大更改。我写的代码或多或少看起来像这样:
COM_GenericTransactionItemsDS com_GenericTransactionItemsDS = new COM_GenericTransactionItemsDS();
long lastUID = 0;
using (SqlConnection sqlConnection = new SqlConnection("...")
{
sqlConnection.Open();
SqlCommand sqlCommand = new SqlCommand("SELECT MAX(UID) FROM COM_GenericTransactionItems WHERE COMControlIn_UID = " + p_COMControlIn_UID, sqlConnection);
//because apparently I'm not allowed to straight cast...
long maxUID = Convert.ToInt64(sqlCommand.ExecuteScalar());
while (lastUID < maxUID)
{
com_GenericTransactionItemsDS.Clear();
using (SqlDataAdapter sqlDataAdapter = new SqlDataAdapter())
{
//Build Select
string strSQL = "SELECT TOP(" + fetchAmount + ") " + SQL_Columns + " FROM COM_GenericTransactionItems " +
"WHERE COMControlIn_UID = " + p_COMControlIn_UID.ToString() + " AND UID > " + lastUID + " ORDER BY UID";
//Get Data
sqlDataAdapter.SelectCommand = new SqlCommand(strSQL, sqlConnection);
sqlDataAdapter.SelectCommand.CommandTimeout = Convert.ToInt32(context.strContext[(int)eCCE_Context._COMMAND_TIMEOUT]);
sqlDataAdapter.Fill(com_GenericTransactionItemsDS, "COM_GenericTransactionItems");
lastUID = com_GenericTransactionItemsDS.COM_GenericTransactionItems.Max(r => r.UID);
}
yield return com_GenericTransactionItemsDS;
}
}
它非常适合获取数据并且显着降低了我们的内存使用量,但是我遇到了一个问题。
我需要通过特定列(日期)对此表中的项目进行分组,但这一概念与整个批处理方法冲突,因为您需要知道整个数据集的外观是什么样的。
我无法在SQL中进行分组,因为在切换到使用此方法之前,我需要像Linq这样的键值对中的数据(除非有办法让我这样做)这在SQL中。)
当我尝试使用SelectMany
将所有行展平为一个可枚举时,每当我尝试访问其中任何行时,我都会RowNotInTableException
。我真的不知道还有什么可以尝试。
作为参考,这是我用来进行分组的Linq查询:
var dateGroups = from row in p_COM_GenericTransactionItemsDS.SelectMany(c => c.COM_GenericTransactionItems) group row by (DateTime)row[tableDefinitions.CaptureDate] into groups select groups;
我认为问题在于我从流媒体方法返回数据的方式,但我不知道如何做到这一点。理想情况下,我希望将数据表中的所有行提取到IEnumerable
中,然后重复执行,但DataRows
不要保留表格的模式(我已经读过架构保存在与它们相关的DataTable
中,所以一旦从数据集中删除它们,它们就基本没用了。
答案 0 :(得分:0)
我解决了我的问题。我改变了我的流式方法来循环遍历它在批处理中接收的项目,复制它们并逐个返回它们,如下所示:
foreach (COM_GenericTransactionItemsDS.COM_GenericTransactionItemsRow row in com_GenericTransactionItemsDS.COM_GenericTransactionItems.Rows)
{
lastUID = row.UID;
COM_GenericTransactionItemsDS.COM_GenericTransactionItemsRow newRow = com_GenericTransactionItemsDS.COM_GenericTransactionItems.NewCOM_GenericTransactionItemsRow();
newRow.ItemArray = row.ItemArray;
yield return newRow;
}