我有一个查询表的记录计数的方法。 QA发现了一个"边缘案例"如果特定操作以特定顺序和速度(尽可能快)取消,GUI"忘记"关于该表中的其余记录(表的内容被上传到服务器;当每个表完成时,相应的表被删除)。
要清楚的是,这个从中删除了记录然后查询计数的表(" workTables")是一个表名表,在处理后会被删除。
我所确定的(我非常确定)是这种异常发生在来自" workTables"当查询workTables表的记录计数时,表正在被删除。这会导致异常,导致方法返回-1,在我们的例子中,我们应该指示GUI不要显示那些记录。
有没有办法检查表是否正在从中删除记录,并等到该操作完成后再继续查询,以便它不会抛出异常?
对于那些对细节感兴趣的人,这种方法是在这些特殊情况下抛出异常的方法:
public int isValidTable(string tableName)
{
int validTable = -1;
string tblQuery = "SELECT COUNT(*) FROM ";
tblQuery += tableName;
openConnectionIfPossibleAndNecessary();
try
{
SqlCeCommand cmd = objCon.CreateCommand();
cmd.CommandText = tblQuery;
object objcnt = cmd.ExecuteScalar();
validTable = Int32.Parse(objcnt.ToString());
}
catch (Exception ex)
{
validTable = -1;
}
return validTable;
}
...这是从" workTables"删除记录的方法。相应表格上传其内容后的表格:
private void DropTablesAndDeleteFromTables(string recordType, string fileName)
{
try
{
WorkFiles wrkFile = new WorkFiles();
int tableOK = 0;
DataSet workfiles;
tableOK = wrkFile.isValidWorkTable(); // -1 == "has no records"
if (tableOK > 0) //Table has at least one record
{
workfiles = wrkFile.getAllRecords();
//Go thru dataset and find filename to clean up after
foreach (DataRow row in workfiles.Tables[0].Rows)
{
. . .
dynSQL = string.Format("DELETE FROM workTables WHERE filetype = '{0}' and Name = '{1}'", tmpType, tmpStr);
dbconn = DBConnection.GetInstance();
dbconn.DBCommand(dynSQL, false);
populateListBoxWithWorkTableData();
return;
} // foreach (DataRow row in workfiles.Tables[0].Rows)
}
}
catch (Exception ex)
{
SSCS.ExceptionHandler(ex, "frmCentral.DropTablesAndDeleteFromTables");
}
}
// method called by DropTablesAndDeleteFromTables() above
public int isValidWorkTable() //reverted to old way to accommodate old version of DBConnection
{
// Pass the buck
return dbconn.isValidTable("workTables");
}
我知道这段代码非常时髦,而且很笨拙;重构它以使其更有意义并且更容易理解是一个漫长而持续的过程。
我无法测试此代码:
lock (this)
{
// drop the table
}
...但是,因为掌上电脑不再允许我将文件复制到它(我得到,"无法复制[filename。[dll,exe]设备已停止响应或已断开连接&# 34;( 连接,如ActiveStync所示))
如果这不起作用,我可能要尝试这个:
// global var
bool InDropTablesMethod;
// before querying that database from elsewhere:
while (InDropTablesMethod)
{
Pause(500);
}
我终于能够测试我的锁码了(二进制文件的副本存在于内存中,不允许我覆盖它们; StartUp文件夹有一个* .lnk到.exe,所以每次我开始掌上电脑,它试图运行.exe的错误版本,但它没有工作 - 我仍然得到相同的冲突/争用。
似乎有用的东西,就像它可能是kludgy一样:
public class CCRUtils
{
public static bool InDropTablesMethod;
. . .
if (CCRUtils.InDropTablesMethod) return;
CCRUtils.InDropTablesMethod = true;
. . . // do it all; can you believe somebody from El Cerrito has never heard of CCR?
CCRUtils.InDropTableMethod = false;
写得太快 - 错误又回来了。我添加了这个MessageBox.Show(),确实看到了文本"代码重新入侵的证明"在运行时。
while (HHSUtils.InDropTablesMethod)
{
MessageBox.Show("proof of code re-entrancy");
i++;
if (i > 1000000) return;
}
try
{
HHSUtils.InDropTablesMethod = true;
. . .
}
HHSUtils.InDropTablesMethod = false;
...所以我猜测代码重入可能是一个问题是正确的......