Как я могу приостановить 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;
... так что мое предположение, что повторный вход кода может быть проблемой, является правильным...