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 задано значение больше единицы, методы навигации (Move, MoveFirst, MoveLast, MoveNext и MovePrevious) могут привести к переходу к удаленной записи, если удаление происходит после извлечения записей. После первоначальной выборки последующие удаления не будут отражаться в кэше данных до тех пор, пока вы не попытаетесь получить доступ к значению данных из удаленной строки. Однако установка значения CacheSize, равного единице, устраняет эту проблему, поскольку удаленные строки не могут быть извлечены.

Тем не менее, я на 100% уверен, что запись, которую я пытаюсь удалить, еще не удалена.

Но, возможно, повторная синхронизация перед поиском поможет избежать проблемы.


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