Получавам това изключение:
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 може да избегне проблема..