2016-05-13 6 views
2

если я выполнить запрос какExecuteCompleted из ADOConnection не уволен, если данные изменений пользователя через DBGrid

Update Table Set aField = 1 Where tablePk = 1 

я могу получить пораженные записи счетчика (параметр RecordsAffected) от ExecuteComplete случае AdoConneciton. Но если я изменяю данные через dbgrid, событие ExecuteComplete не запускается.

Как я могу получить зараженное количество записей после команды insert/update/delete, которая была выполнена dbgrid?

+1

Используйте событие AfterPost для ADOQuery или ADOTable, которое подключено к DBGrid. Будет обновлена ​​только одна запись, поэтому вы знаете счет заранее. –

+0

@KenWhite, проект содержит около 100 adoquery, прикрепленных к dbGrids. я хотел сделать это, используя соединение, но это швы невозможно. – sddk

ответ

4

Я не думаю, что есть способ получить количество строк, затронутых при обновлении, вставляет и удаляет через TDBgrid или другие компоненты, поддерживающие DB, такие как TDBNavigator. Причина в том, что элементы управления, поддерживающие DB, вызывают методы Post и Delete TDataSet, а эти вызовы переопределяют InternalPost и InternalDelete в TAdoCustomDataSet. Они работают принципиально иначе, чем выполнение инструкции SQL с помощью метода ExecSql, скажем, TAdoQuery.

По дизайну TDataSet.Post и TDataSet.Delete должны влиять только на одну строку, поэтому, если операция завершается успешно, вы знаете, что была затронута только одна строка.

Стоит отметить, хотя и не очень поможет за то, что вы хотите сделать, что это способ прикрепить один и тот же обработчик события к числу из TAdoCustomDataSet потомков, которые разделяют TADOConnection, как показано в следующем коде:

procedure TForm1.FormCreate(Sender: TObject); 
var 
    i : Integer; 
begin 
    for i := 0 to AdoConnection1.DataSetCount - 1 do 
    AdoConnection1.DataSets[i].AfterPost := AfterPost; 
    AdoQuery1.Open; 
    AdoQuery2.Open; 
end; 

procedure TForm1.AfterPost(DataSet: TDataSet); 
var 
    Q : TAdoQuery; 
begin 
    if DataSet is TAdoQuery then begin 
    Q := TAdoQuery(DataSet); 
    Caption := IntToStr(Q.RowsAffected); 
    end 
    else 
    Caption := 'Post'; 
end; 

конечно, если наборы данные, участвующие уже имеют свои собственные обработчик событий, вам потребуется какая-то структура для хранения существующих обработчиков и цепи права одного из них в общем обработчике (фи TForm1.AfterPost выше).

Если вы попробуете приведенный выше код и наблюдаете, что происходит, когда вы публикуете редактирование из DBGrid, который получает данные из TAdoQuery, вы увидите, что, к сожалению, RowsAffected равен нулю. Это потому, что TAdoQuery's FRowsAffected обновляется только тогда, когда вызывается его метод ExecSql, и он не получает вызовы для операций набора данных , вызываемых через DBGrid. Разница заключается в том, что OnExecuteComplete AdoConnection вызывается из объекта Command, используемого для выполнения TAdoQuery's ExecSql. Операции, инициированные с помощью DBGrid, otoh, вызывают методы объекта RecordSet, связанного с TAdoCustomDataSet, в его InternalPost и InternalDelete, и не вызывают OnExecuteComplete AdoConnection.

Объекты RecordSet имеют свои собственные наборы событий, см. F.i. RecordSetEvents в ADOInt.Pas, и, возможно, вы могли бы настроить общие обработчики событий для тем же способом, что и общий пример события AfterPost выше. Тем не менее, Я не думаю, что это сделало бы что-нибудь полезное для вас, если вы хотите получить значение RowsAffected для TDataset. Вставить/Обновить/Удалить, вызванное из DB123 (или, скажем, TDBNavigator, подключенного к его TDataSource).

Поэтому я говорю, что это то, что если вы посмотрите на исходный код для метода в TAdoCustomDataSet InternalPost вы увидите, что она включает в себя

if State = dsEdit then 
    UpdateData 
    else 
    begin 
    Recordset.AddNew(EmptyParam, EmptyParam); 
    try 
     UpdateData; 
    except 

и вложенная UpdateData делает свои вещи на вызывая

Recordset.Update(EmptyParam, EmptyParam); 

Теперь, если вы посмотрите на документации MS для RecordSet.Update, вы увидите, например,

https://msdn.microsoft.com/en-us/library/ecc2bf09.aspx?f=255&MSPPError=-2147217396

в котором четко говорится, что если Update не влияет на ровно одну запись, исключение. Я думаю, это то, о чем говорил @KenWhite, когда он сказал «Будет обновлена ​​только одна запись». Поэтому, если RecordSet.Update успешно завершен, вы знаете, что затронута только одна строка.

Я не проверял, но так как TAdoCustomDataSet.InternalDelete использует свой объект для удаления, аналогичный, вероятно, будет прав.

+0

спасибо за очень хорошо объясненный ответ. я проверю, что можно сделать в проекте, зная, что выполняется обновление/вставка/редактирование, но не зная RowsAffected. – sddk