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 上?的主要内容,如果未能解决你的问题,请参考以下文章
C#两个DataTable拷贝问题:该行已经属于另一个表的解决方法
vs2010 asp.net 中,怎么将一个DataTable中的某行数据 复制给另一个DataTable中。
重用数据表或我是以错误的方式...:DataTable已经属于另一个DataSet