Перехват EOleException при работе с TADODataSet в многопользовательской среде
При работе с компонентом TADODataSet в среде, где работает несколько пользователей, может возникать исключение, указывающее на то, что строка не может быть найдена для обновления. Это происходит, когда некоторые значения были изменены с момента последнего чтения. В зависимости от того, запускается ли программа из среды разработки или вне неё, тип исключения может отличаться. В IDE исключение поднимается как EOleException с кодом ошибки -2147217864, в то время как вне IDE - как EDatabaseError, который не содержит нужного для анализа ErrorCode.
Проблема
Когда пользователь редактирует TADODataSet и выполняет операцию Post, может возникнуть исключение, связанное с ADO. В частности, сообщение об ошибке гласит: "Row cannot be located for updating. Some values may have been changed since it was last read.".
Если программа запущена в среде разработки, исключение EOleException с кодом -2147217864 поднимается при вызове метода Post в процедуре DataSetCommit. Однако, при выполнении программы вне среды разработки, исключение перехватывается как EDatabaseError, не содержащий необходимого ErrorCode.
Пример кода
Вот пример кода, который демонстрирует обработку исключений при работе с TADODataSet:
procedure TForm1.DataSetCommit(ds: TADODataSet);
begin
ds.Connection.BeginTrans;
try
try
ds.Post; // Возможное место возникновения исключения
except
on E: EDatabaseError do
begin
if Assigned(ds.Connection.Errors) and (ds.Connection.Errors.Count > 0) then
with ds.Connection.Errors.Item[0] do
// Проверка на нужный код ошибки
if Number = -2147217864 then
// Обработка ошибки
ShowMessage(Format('Number:%d; Source:%s; Description:%s; NativeError:%d; SQLState:%s',
[Number, Source, Description, NativeError, SQLState]));
end;
end;
ds.Connection.CommitTrans;
except
ds.Connection.RollbackTrans;
raise;
end;
end;
Обработка ошибок
Внутренняя реализация TADODataSet оборачивает исключения, что приводит к потере оригинального EOleException. В коде ADODB.TCustomADODataSet.InternalPost можно увидеть, что исключение, возникающее внутри процедуры UpdateData, оборачивается в EDatabaseError.
Решение
Один из способов решения проблемы - это использование объекта Errors соединения TADODataSet. Это позволяет получить доступ к информации об ошибке, даже если исходное исключение было обернуто.
procedure TForm1.DataSetCommit(ds: TADODataSet);
begin
ds.Connection.BeginTrans;
try
try
ds.Post;
except
on E: EDatabaseError do
begin
if Assigned(ds.Connection.Errors) and (ds.Connection.Errors.Count > 0) then
with ds.Connection.Errors.Item[0] do
// Проверка и обработка каждой ошибки в списке
ShowMessage(Format('Number:%d; Source:%s; Description:%s; NativeError:%d; SQLState:%s',
[Number, Source, Description, NativeError, SQLState]));
end;
end;
ds.Connection.CommitTrans;
except
ds.Connection.RollbackTrans;
raise;
end;
end;
Этот метод специфичен для работы с TADODataSet и позволяет обработать ошибку без необходимости вмешательства в RTL.
Альтернативные подходы
Существуют и другие идеи по перехвату EOleException, например, использование System.RaiseList или модификация RTL, но эти подходы могут быть более сложными и специфичными.
Заключение
При работе с TADODataSet в многопользовательской среде важно уметь корректно обрабатывать исключения. Использование объекта Errors соединения позволяет получить доступ к информации об ошибке, даже если оригинальное исключение было потеряно. Это простой и эффективный способ решения проблемы, описанной в вопросе.
Проблема заключается в перехвате исключения `EOleException` при обновлении данных в `TADODataSet` в многопользовательском режиме, с целью корректной обработки ошибки, связанной с изменением данных после их последнего чтения.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.