Код в порядке в DAO, но выдает ошибку времени выполнения «3021» в ADO - PullRequest
2 голосов
/ 13 мая 2011

Это происходит после замены DAO на ADO в проекте VB6, который использует базу данных Access 97.

Это происходит в строке с пометкой «Ошибка здесь» в следующем фрагменте:

If rset.BOF <> True Or rset.EOF <> True Then
  rset.MoveLast 
  Do While rset.BOF <> True
     rset.Delete
     If rset.BOF <> True Or rset.EOF <> True Then  
         rset.MoveLast    'Error Here
     End If
   Loop
End If

Ошибка времени выполнения «3021» дает это объяснение:

"EOF или BOF - True, или текущая запись была удалена. запрашиваемая операция требует тока запись. "

Похоже, что после удаления последней записи в наборе записей BOF +/- EOF все еще имеет значение false в версии кода ADO, в то время как обе версии имеют значение true в версии DAO. Если я изменю код таким образом, он будет работать

РЕДАКТИРОВАТЬ: следующий код НЕ работает. Когда я попробовал это «решение» все записи были уже удалены из таблицы, поэтому весь блок был обойден, и поэтому не было выдано никакой ошибки. Извините за плохую информацию.

If rset.BOF <> True Or rset.EOF <> True Then
      rset.MoveLast 
      Do While rset.BOF <> True
         rset.Delete
         If rset.BOF <> True Or rset.EOF <> True Then 
         End If
         If rset.BOF <> True Or rset.EOF <> True Then  
             rset.MoveLast    
         End If
       Loop
End If

Может кто-нибудь объяснить это? (и в идеале предложить решение, которое не требует изменения кода!)

ДОПОЛНИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ: насколько я могу судить, перепробовав множество способов, BOF и EOF бесполезны в ADO для тестирования пустого набора записей после удаления. Это потому, что вам нужно использовать один из методов перемещения для обновления BOF / EOF, и если набор записей пуст, вы получите ошибку. На наборе записей, который я использовал, свойство RecordCount обновлялось после удаления. Хотя я не собираюсь его использовать, этот код сделал работает:

If rset.BOF <> True Or rset.EOF <> True Then
   Do While rset.RecordCount > 0
      rset.MoveLast
      rset.Delete
   Loop
End If

Редактировать (1 месяц спустя) Поэтому после переписывания целой кучи кода я наткнулся на цикл, содержащий удаление, которое не выдает ошибку. Единственное отличие заключалось в том, что этот цикл удалял первую запись в наборе записей каждый раз, а не последнюю, и поэтому после каждого удаления выполнялся скорее, чем MOVELAST. Поэтому я максимально сократил код, и следующий фрагмент отлично работает как на Postgresql, так и на Access - двух базах, которые я пробовал, с VB6 с использованием ADO.

Do While rset.EOF <> True
     rset.Delete
     rset.MoveFirst
Loop

После удаления окончательной записи EOF и BOF по-прежнему остаются ложными, но вы не получите ошибку при вызове метода MOVEFIRST. Вызов MOVEFIRST теперь устанавливает для EOF и BOF значение true, и цикл завершается. Напротив, если метод MOVEFIRST заменен на MOVELAST, то ошибка (3021) возникает в обеих базах данных. В своем ответе rskar процитировал это из MSDN

Используйте метод MoveNext для перемещения текущая позиция записи одна запись вперед (к нижней части Recordset). Если последняя запись текущая запись и вы называете Метод MoveNext, ADO устанавливает текущий запись на позицию после последней запись в наборе записей (EOF - True). Попытка двигаться вперед, когда Свойство EOF уже True генерирует ошибка.

Они упоминают, что MOVENEXT вызывает ошибку, и я полагаю, поскольку MOVELAST движется в том же направлении, это объясняет, почему оно также вызывает ошибку. Хотелось бы, чтобы я не предполагал, что все методы перемещения приведут к подобным проблемам

1 Ответ

3 голосов
/ 13 мая 2011

См. http://msdn.microsoft.com/en-us/library/ms675787(v=vs.85).aspx:

Если вы удалите последнюю оставшуюся запись в объекте Recordset, свойства BOF и EOF могут оставаться False до тех пор, пока вы не попытаетесь изменить положение текущей записи.

Поскольку ADO не DAO, различия в поведении не должны быть слишком удивительными.Казалось бы, вызов MoveLast может вызвать обновление BOF / EOF.Я думаю, что вы можете быть вынуждены внести изменения в код.

Для ударов и хихиканья, попробуйте (не знаю, сработает ли):

rset.Delete 
rset.MoveNext
If rset.BOF <> True Or rset.EOF <> True Then                 
    rset.MoveLast               
End If

За http://msdn.microsoft.com/en-us/library/ms677527(v=vs.85).aspx:

Используйте метод MoveNext для перемещения текущей позиции записи на одну запись вперед (к нижней части набора записей).Если последняя запись является текущей записью, и вы вызываете метод MoveNext, ADO устанавливает текущую запись в положение после последней записи в наборе записей (EOF - True).Попытка двигаться вперед, когда свойство EOF уже имеет значение True, приводит к ошибке.

...