DataTable 'Table' 已经属于这个数据集 - 在新的数据集上?

DataTable 'Table' already belongs to this DataSet - on a new DataSet?

我有一个执行 SQL 查询的函数和 return 查询结果的通用数据集。这个功能已经在许多应用程序中工作多年,但今天我得到了一个特定的查询

"Error executing [select top (1) RecordId, SourceCID, SourceID, CaseID, DisposeRequestedDate, DisposeRequestedBy, DisposeApprovedDate, DisposeApprovedBy from mycatalog.dbo.CASD_RetentionManagementDisposalApprovedQueue order by DisposeApprovedDate, RecordID;] A DataTable named 'Table' already belongs to this DataSet."

函数是

    public static DataSet ExecSQLQuery(string sqlQuery)
    {
      mDataSet = new DataSet();
      ...  // setup, but NO references to mDataSet
      try {
         ...  // establish, open connection as "conn"
         mDataAdapter = new SqlDataAdapter(new SqlCommand(sqlQuery, conn));
         mDataAdapter.Fill(mDataSet);
      } catch (Exception ex) {
         //  this traps "A DataTable named 'Table' already belongs to this DataSet."
         Log("Error executing [" + sql + "]" + ex.message);
      }
      finally {
         if (conn != null)
         {
            if (conn.State == ConnectionState.Open)
               conn.Close();
            conn.Dispose();
         }
      }
      return mDataSet;
    }

调用过程基本上是:

public static ProcessResult ProcessDestructQueue()
{
    // maxRecords is a configuration setting, currently set to 1
            string sql = "select top (" + maxRecords.ToString() + ") RecordId, SourceCID, SourceID, CaseID, DisposeRequestedDate, DisposeRequestedBy, DisposeApprovedDate, DisposeApprovedBy " +
                " from mycatalog.dbo.CASD_RetentionManagementDisposalApprovedQueue " +
                " order by DisposeApprovedDate, RecordID;";
            DataSet ds = null;
    try {
        sWhere = "exec query [ " + sql + " ]";
        ds = SQLUtility.ExecSQLQuery(sql);
        if (!SQLUtility.IsValidDataSet(ds))
        {
            if (!SQLUtility.IsValidButEmptyDataSet(ds))
                throw new Exception("Failed to get a valid data set with [ " + sql + " ]");
            //
            //  no records to process
            //
            return ProcessResult.NOFILESTOPROCESS;
        }
    }
    catch (...) { ... }
    finally {
       if (ds != null)
         ds.Dispose();
    }
    ...
    }

当我的配置参数设置为 1 (Select top (1) ...) 时,出现错误。当设置为2时,(Select top(2) ...),不会出现该错误。 “Select top (1)...”有什么独特之处还是我做错了什么? 顺便说一句 - table 当前为空,因此前 1 和前 2 都不应该 return 任何行。

根据要求 - IsValidDataSet 和 IsValidButEmptyDataSet 方法:

public static bool IsValidDataSet(DataSet ds)
{
    if (ds != null)
        if (ds.Tables.Count > 0)
            if (ds.Tables[0] != null)
                if (ds.Tables[0].Rows.Count > 0)
                    if (ds.Tables[0].Rows[0] != null)
                        if (ds.Tables[0].Rows[0].ItemArray.Length > 0)
                            return true;
    return false;
}
public static bool IsValidButEmptyDataSet(DataSet ds)
{
    if (ds == null || ds.Tables.Count == 0 || ds.Tables[0].Rows.Count == 0)
        return true;
    return false;
}

根据要求 - 来自错误的堆栈跟踪: 堆栈跟踪: 在 System.Data.DataTableCollection.RegisterName(字符串名称,字符串 tbNamespace) 在 System.Data.DataTableCollection.BaseAdd(数据表 table) 在 System.Data.DataTableCollection.Add(数据表 table) 在 System.Data.ProviderBase.SchemaMapping.SetupSchemaWithoutKeyInfo(MissingMappingAction mappingAction、MissingSchemaAction schemaAction、布尔值 gettingData、DataColumn parentChapterColumn、对象 chapterValue) 在 System.Data.ProviderBase.SchemaMapping..ctor(DataAdapter 适配器、DataSet 数据集、DataTable 数据table、DataReaderContainer dataReader、Boolean keyInfo、SchemaType schemaType、String sourceTableName、Boolean gettingData、DataColumn parentChapterColumn、Object parentChapterValue) 在 System.Data.Common.DataAdapter.FillMappingInternal(DataSet 数据集、DataTable 数据table、String srcTable、DataReaderContainer dataReader、Int32 schemaCount、DataColumn parentChapterColumn、Object parentChapterValue) 在 System.Data.Common.DataAdapter.FillMapping(DataSet 数据集、DataTable 数据table、String srcTable、DataReaderContainer dataReader、Int32 schemaCount、DataColumn parentChapterColumn、Object parentChapterValue) 在 System.Data.Common.DataAdapter.FillFromReader(DataSet 数据集、DataTable 数据table、String srcTable、DataReaderContainer dataReader、Int32 startRecord、Int32 maxRecords、DataColumn parentChapterColumn、Object parentChapterValue) 在 System.Data.Common.DataAdapter.Fill(DataSet 数据集、字符串 srcTable、IDataReader dataReader、Int32 startRecord、Int32 maxRecords) 在 System.Data.Common.DbDataAdapter.FillInternal(DataSet 数据集、DataTable[] 数据tables、Int32 startRecord、Int32 maxRecords、String srcTable、IDbCommand 命令、CommandBehavior 行为) 在 System.Data.Common.DbDataAdapter.Fill(DataSet 数据集、Int32 startRecord、Int32 maxRecords、String srcTable、IDbCommand 命令、CommandBehavior 行为) 在 System.Data.Common.DbDataAdapter.Fill(数据集数据集) 在 SQLUtility.ExecSQLQuery(字符串 sqlQuery,布尔值 ignoreError)

相信我已经弄清楚发生了什么。
我的 ExecSQLQuery 方法不是线程安全的(它是一个 public 静态方法),但我有两个独立的计时器 运行。如果计时器 2 在计时器 1 处理序列当前正在该方法内执行时触发,则第二个可以结束调用同一过程。当计时器 2 进程终止时,第一个代码恢复,但局部变量现在已经加载,导致“'Table' 已经属于数据集”错误。 我添加了很多诊断代码,发现这只是在两个定时器触发的大量执行之后才会发生。 我将添加一个信号量以防止一个进程在另一个进程已在执行时执行。