DataTable 'Table' 已经属于这个 DataSet - 在一个新的 DataSet 上?

Posted

技术标签:

【中文标题】DataTable \'Table\' 已经属于这个 DataSet - 在一个新的 DataSet 上?【英文标题】:DataTable 'Table' already belongs to this DataSet - on a new DataSet?DataTable 'Table' 已经属于这个 DataSet - 在一个新的 DataSet 上? 【发布时间】:2021-02-21 22:34:35 【问题描述】:

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

"错误执行[select top (1) RecordId, SourceCID, SourceID, CaseID、DisposeRequestedDate、DisposeRequestedBy、DisposeApprovedDate、 DisposeApprovedBy 来自 mycatalog.dbo.CASD_RetentionManagementDisposalApprovedQueue order by DisposeApprovedDate, RecordID;] 已经有一个名为“表”的数据表 属于这个数据集。”

功能是

    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(选择顶部 (1) ...)时,我收到错误消息。当设置为 2, (Select top (2) ...) 时,不会发生错误。 “选择顶部(1)......”有什么独特之处还是我做错了什么? 顺便说一句 - 表当前是空的,所以 top 1 和 top 2 都不应该返回任何行。

根据要求 - 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(DataTable 表) 在 System.Data.DataTableCollection.Add(DataTable 表) 在 System.Data.ProviderBase.SchemaMapping.SetupSchemaWithoutKeyInfo(MissingMappingAction mappingAction,MissingSchemaAction schemaAction,布尔获取数据,DataColumn parentChapterColumn,对象 chapterValue) 在 System.Data.ProviderBase.SchemaMapping..ctor(DataAdapter 适配器,DataSet 数据集,DataTable 数据表,DataReaderContainer dataReader,布尔 keyInfo,SchemaType schemaType,字符串 sourceTableName,布尔 gettingData,DataColumn parentChapterColumn,对象 parentChapterValue) 在 System.Data.Common.DataAdapter.FillMappingInternal(DataSet 数据集、DataTable 数据表、String srcTable、DataReaderContainer dataReader、Int32 schemaCount、DataColumn parentChapterColumn、Object parentChapterValue) 在 System.Data.Common.DataAdapter.FillMapping(DataSet 数据集、DataTable 数据表、String srcTable、DataReaderContainer dataReader、Int32 schemaCount、DataColumn parentChapterColumn、Object parentChapterValue) 在 System.Data.Common.DataAdapter.FillFromReader(DataSet 数据集,DataTable 数据表,字符串 srcTable,DataReaderContainer dataReader,Int32 startRecord,Int32 maxRecords,DataColumn parentChapterColumn,对象 parentChapterValue) 在 System.Data.Common.DataAdapter.Fill(DataSet 数据集,字符串 srcTable,IDataReader dataReader,Int32 startRecord,Int32 maxRecords) 在 System.Data.Common.DbDataAdapter.FillInternal(DataSet 数据集,DataTable[] 数据表,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(String sqlQuery, Boolean ignoreError)

【问题讨论】:

maxRecords 是否在其他地方使用?调用 ExecSQLQuery(在 try 块中)之后会发生什么?你能发布一个完整的、缩小的例子吗? 我围绕这两部分填写了所有相关代码。在调用 ExecSQLQuery 之后,我调用了两个函数,它们告诉我我是否有一个有效的(非空的)结果,或者一个有效的结果,但没有返回任何行。 maxRecords 用于另一个类似的查询(针对不同的表,具有不同的列)。另一个查询正确返回,没有错误。错误是在 ExecSQLQuery 函数中引发的——返回之后的代码将如何影响该错误? 以防万一它有任何相关性,此代码位于 Windows Server 2016、SQL Server 2016 上的服务中 - 而不是 Windows 桌面客户端应用程序中。 请显示其他方法主体(IsValidDataSet 和 IsValidButEmptyDataSet)。另外,完整的堆栈跟踪是什么? 我需要捕获并输出堆栈跟踪(明天)——这是一个在远程服务器上运行的服务。其他方法现在在原帖中。 【参考方案1】:

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

【讨论】:

是的。我添加了一些陷阱,确认我得到了一些进程线程交互。随着信号量停止并发调用,错误不再发生。 太好了,感谢您的更新,很高兴您整理好了。

以上是关于DataTable 'Table' 已经属于这个 DataSet - 在一个新的 DataSet 上?的主要内容,如果未能解决你的问题,请参考以下文章

DataTable 已经属于另一个 DataSet

C#两个DataTable拷贝问题:该行已经属于另一个表的解决方法

vs2010 asp.net 中,怎么将一个DataTable中的某行数据 复制给另一个DataTable中。

重用数据表或我是以错误的方式...:DataTable已经属于另一个DataSet

System.ArgumentException: 该行已经属于另一个表。看下面代码

DataTable获取tr的数据