0

目前,我正在使用的应用程序使用强类型DataSets 来处理来自数据库的数据。我们有一个称为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它们相关的位置),所以一旦你从数据集中删除它们,它们基本上就没有用了。

4

1 回答 1

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;
}
于 2015-02-11T07:39:29.667 回答