ADO Insert и Delete, выполняющиеся на 2 разных соединениях, вызывают ошибки - PullRequest
0 голосов
/ 28 декабря 2011

Проблема:
Я вижу комбинацию E_FAIL и повреждения базы данных в каждом из двух потоков, каждый из которых имеет свое собственное соединение, открытое для Jet 4.0 MDB.

Сценарий:
У меня есть приложение, где:

Нить 1 является основной нитью.Он имеет ADO-соединение, открытое для Jet 4.0 mdb, используя провайдера «Microsoft.Jet.OLEDB.4.0».Он отвечает за вставку данных в одну из двух таблиц, расположенных в базе данных mdb, через

hr = pADOConn->Execute("INSERT INTO ...", NULL, adCmdText|adExecuteNoRecords, NULL);
// occasionally returns E_FAIL

Поток 2 является дочерним по отношению к потоку 1. Он также имеет соединение ADO, открытое с точно такой же строкой соединения.Он отвечает за итерацию записей, уже присутствующих в каждой из двух таблиц, «подкачку» каждой строки на сервер и затем удаление строки из таблицы.Это достигается с помощью (сокращенно только для соответствующих частей):

countSQL = "select count(*) from TABLE";
iRecCount = pADORstTable->Open(countSQL, pADOConn2, adOpenKeyset, adLockOptimistic, adCmdText);

for (iRecCtr = 0; iRecCtr < iRecCount; iRecCtr++)
{
   // provides the capability to skip records
   strSQL = "SELECT TOP 1 * FROM (SELECT TOP " + iSkipRecords + 
            " * FROM TABLE ORDER BY PriKey DESC)";

   pADORst->Open(strSQL, pADOConn2, adOpenKeyset, adLockOptimistic, adCmdText);
   pADORst->get_EOF(&vbEOF);
   if (vbEOF)
      break;
   RstPriKey = GetFieldValueForPriKey(pADORst);
   pADORst->Close();
   pADORst->Release();

   // pump record to server
   ...

   // delete record
   bstrSQL = "delete from TABLE where PriKey = " + RstPriKey;
   hr = pADOConn2->Execute(bstrSQL, NULL, adCmdText|adExecuteNoRecords, NULL);
   // occasionally returns E_FAIL
}


Обходные пути:

  • Первоначально было закодировано для использованияодиночное соединение, на которое дочернему потоку был передан указатель.С тех пор мы разделили его на два отдельных соединения.
  • Код изначально создал набор записей ado для выполнения вставки и использовал базовый набор записей ADO для выполнения pADORst-> Delete ().С тех пор оба были изменены, чтобы использовать Conn-> Execute (...)
  • Наша следующая мысль - перейти к реализации критического раздела и передать его между потоками.Это кажется радикальным, поскольку кажется, что ADO должен быть в состоянии обрабатывать запросы, поступающие из нескольких соединений.
  • Я знаком с размером блокировки страниц Jet 4,0, и мне интересно, если мыудар по нему, и нужно переключиться на блокировку уровня записи.
  • Я буду развлекать чужие мысли, какими бы резкими они ни были ...

Редактировать 1:
Только что попробовал обернуть оба -> Execute () в критическую секцию;по-прежнему время от времени устанавливает E_FAIL из DELETE FROM.

Edit 2:
Также попытался закрыть набор записей сразу после получения значения первичного ключа (код обновлен для отражения изменений)

1 Ответ

1 голос
/ 28 декабря 2011

Есть ли более описательное сообщение об ошибке, которое вы получаете?Я предполагаю, что это нарушение параллелизма.Вы можете попробовать закрыть и выпустить "pADORstTable", так как оба набора записей работают на одной таблицеЯ бы также закрыл и выпустил "pADORst" после EOF.

...