Как я могу приостановить SQLCE-запрос до тех пор, пока к таблице, к которой он обращается, больше не будет обращаться?

У меня есть метод, который запрашивает таблицу для подсчета ее записей. QA обнаружил "крайний случай", когда, если конкретная операция отменяется в определенном порядке и скорости (как можно быстрее), GUI "забывает" об остальных записях в этой таблице (содержимое таблиц загружается на сервер, когда каждый из них заканчивается, соответствующая таблица удаляется).

Для ясности, эта таблица, в которой из нее удаляются записи, а затем запрашивается счетчик ("workTables"), является таблицей имен таблиц, которые удаляются после их обработки.

Я определил (я почти уверен), что эта аномалия возникает, когда запись из таблицы "workTables" находится в процессе удаления, когда к таблице workTables запрашивается количество записей. Это вызывает исключение, которое приводит к тому, что метод возвращает -1, что в нашем случае означает, что мы должны использовать графический интерфейс, чтобы эти записи не отображались.

Есть ли способ проверить, находится ли таблица в процессе удаления из нее записи, и подождать, пока эта операция не будет завершена, прежде чем продолжить выполнение запроса, чтобы она не вызывала исключение?

Для тех, кто интересуется спецификой, этот метод - тот, который в этих специфических обстоятельствах создает исключение:

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
}

... еще, потому что контроллер больше не позволяет мне копировать файлы в него (я получаю: "Не удается скопировать [имя файла.[dll,exe]" Устройство перестало отвечать или было отключено " (оно подключено, так как показывается ActiveStync))

Если это не сработает, я мог бы попробовать это:

// global var
bool InDropTablesMethod;

// before querying that database from elsewhere:
while (InDropTablesMethod)
{
  Pause(500);
}

ОБНОВЛЕНИЕ 2

Наконец-то я смог протестировать свой код блокировки (копии двоичных файлов присутствовали в памяти, что не позволяло мне их перезаписать; папка StartUp содержала *.lnk для.exe, поэтому каждый раз, когда я запускал контроллер, он пытался запустить версии с ошибками.exe), но это не работает - я все еще получаю тот же конфликт / раздор.

ОБНОВЛЕНИЕ 3

То, что, кажется, работает, какой бы хитрой она ни была, это:

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 ответов

Другие вопросы по тегам