EOleException: BOF или EOF е True, или текущият запис е изтрит. Заявената операция изисква текущ запис

Получавам това изключение:

EOleException: BOF или EOF е True, или текущият запис е изтрит. Заявената операция изисква текущ запис

опитвам се да изтрия запис:

if SetupTable.Locate('MyFieldName', AKey, []) then
  SetupTable.Delete

Това, което се случва тук е, че има проверка дали съществува запис в базата данни и ако е така, той се изтрива. Проблемът ми е, че записът съществува, но изтриването му води до горното изключение.

Това е настройка за един потребител и няма начин записът да изчезне между изпълнението на тези два реда.

Този код работи добре от 8 години. Изключението се случва само в Windows 8. Виждал съм го в 5 различни клиентски сайта. Клиентите, използващи Windows XP, Vista, 7, не виждат проблема.

Използвам Delphi XE за достъп до база данни на MS Access чрез ADO с доставчик Microsoft.Jet.OLEDB.4.0

ето дъмп на стека:

0073f59d DSALon.exe   ADODB         4712 DoRecordsetDelete
0073f5b6 DSALon.exe   ADODB         4719 TCustomADODataSet.InternalDelete
006b3dd1 DSALon.exe   DB           12947 TDataSet.CheckOperation
006b3ad8 DSALon.exe   DB           12856 TDataSet.Delete
007cade6 DSALon.exe   DatabaseUnit   629 ClearSetup

Нарушителният код в ADODB изглежда така:

procedure DoRecordsetDelete(DataSet: TCustomADODataSet; AffectRecords: TAffectRecords);
begin
  with DataSet do
  try
    Recordset.Delete(AffectRecordsValues[AffectRecords]);
    { When CacheSize > 1, Recordset allows fetching of deleted records.
      Calling MovePrevious seems to work around it }
    if (CacheSize > 1) and (PRecInfo(ActiveBuffer).RecordNumber <> 1) then
    begin
      Recordset.MovePrevious;
      Recordset.MoveNext;
    end;
    Recordset.MoveNext;
  except
    on E: Exception do
    begin
      Recordset.CancelUpdate;
      DatabaseError(E.Message);
    end;
  end;
end;

което ме кара да мисля, че CacheSize е подходящ тук. Използвам CacheSize > 1.

Помощта на MSDN за свойството ADO CacheSize казва:

Ако CacheSize е зададен на стойност, по-голяма от единица, методите за навигация (Преместване, ПреместванеПърво, ПреместванеПоследно, ПреместванеСледващ и Преместванепредишен) може да доведат до навигация към изтрит запис, ако изтриването се случи след извличането на записите. След първоначалното извличане последващите изтривания няма да бъдат отразени в кеша ви за данни, докато не опитате да получите достъп до стойност на данни от изтрит ред. Задаването на CacheSize на единица обаче елиминира този проблем, тъй като изтритите редове не могат да бъдат извлечени.

Все пак съм 100% сигурен, че записът, който се опитвам да изтрия, вече не е изтрит.

Но може би извършването на Resync преди Locate може да избегне проблема..


person JacobHavkrog    schedule 20.05.2014    source източник
comment
възможен дубликат на Delphi - BOF или EOF е True, или текущият запис е изтрит   -  person Gerry Coll    schedule 20.05.2014
comment
@DavidHeffernan Кодът проверява дали записът все още е там, преди да се опита да го изтрие. Така че не би трябвало да е възможно тази грешка да се случи. Забравих да спомена, че това е настройка за един потребител, редактирах въпроса, за да отрази това. Не изглежда като грешка в моя код.   -  person JacobHavkrog    schedule 20.05.2014
comment
@GerryColl Тази публикация е свързана с Delphi 5. Използвам Delphi XE. И това е нов проблем, въведен с Windows 8.   -  person JacobHavkrog    schedule 20.05.2014
comment
съжалявам, четях на таблет и пропуснах справката за XE   -  person Gerry Coll    schedule 20.05.2014
comment
Бих предложил да тествате някои гранични условия, за да видите дали можете да го симулирате. напр. Уверете се, че кодът изтрива първия запис в набора от записи, последния и може би дори единствения запис.   -  person Disillusioned    schedule 20.05.2014