如何暂停SQLCE查询,直到它查询的表不再被其他地方访问?

时间:2014-09-22 23:38:36

标签: c# sql-server-ce compact-framework windows-ce reentrancy

我有一个查询表的记录计数的方法。 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);
}

更新2

我终于能够测试我的锁码了(二进制文件的副本存在于内存中,不允许我覆盖它们; StartUp文件夹有一个* .lnk到.exe,所以每次我开始掌上电脑,它试图运行.exe的错误版本,但它没有工作 - 我仍然得到相同的冲突/争用。

更新3

似乎有用的东西,就像它可能是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;

更新4

写得太快 - 错误又回来了。我添加了这个MessageBox.Show(),确实看到了文本"代码重新入侵的证明"在运行时。

while (HHSUtils.InDropTablesMethod)
{
    MessageBox.Show("proof of code re-entrancy");
    i++;
    if (i > 1000000) return; 
}
try
{
    HHSUtils.InDropTablesMethod = true;
    . . .               
}
HHSUtils.InDropTablesMethod = false;

...所以我猜测代码重入可能是一个问题是正确的......

0 个答案:

没有答案