2016-05-13 1 views
2

si j'exécutons une requête commeExecuteCompleted de AdoConnection ne se déclenche pas si les données de l'utilisateur via les changements de DBGrid

Update Table Set aField = 1 Where tablePk = 1 

je peux obtenir le nombre d'enregistrements affectés (paramètre RecordsAffected) de l'événement ExecuteComplete de AdoConneciton. Mais si je change de données via dbgrid, l'événement ExecuteComplete n'est pas déclenché.

Comment puis-je obtenir le nombre d'enregistrements affectés après la commande insert/update/delete qui a été exécutée par dbgrid?

+1

Utilisez l'événement 'AfterPost' de l'objet ADOQuery ou ADOTable attaché au DBGrid. Il n'y aura qu'un seul enregistrement mis à jour, donc vous connaissez le compte à l'avance. –

+0

@KenWhite, le projet contient environ 100 adocations attachées à dbGrids. Je voulais le faire en utilisant la connexion, mais il semble que c'est impossible. – sddk

Répondre

4

Je ne pense pas qu'il existe un moyen d'obtenir le nombre de lignes affectées lorsque vous effectuez des mises à jour, insère et supprime via un TDBgrid ou d'autres composants compatibles DB comme TDBNavigator. La raison en est que les contrôles prenant en charge DB utilisent les méthodes Post et Delete de TDataSet et que ces appels remplacent InternalPost et InternalDelete dans TAdoCustomDataSet. Ils fonctionnent d'une manière fondamentalement différente de l'exécution d'une instruction SQL via la méthode ExecSql de, disons, TAdoQuery.

Par conception, TDataSet.Post et TDataSet.Delete ne doivent affecter qu'une seule ligne, donc si l'opération réussit, vous savez que exactement une ligne a été affectée.

Il convient de noter, mais pas beaucoup d'aide pour ce que vous voulez faire, qu'il y est un moyen de fixer le même gestionnaire d'événements à un certain nombre de descendants TAdoCustomDataSet qui partagent un TADOConnection, comme indiqué dans ce code:

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; 

Bien sûr, si les ensembles de données impliqués ont déjà leurs propres gestionnaires d'événements, vous auriez besoin une certaine structure pour stocker les gestionnaires existants et la chaîne à droite un d'entre eux dans le gestionnaire partagé (fi TForm1.AfterPost au dessus).

Si vous essayez le code ci-dessus et observez ce qui se passe lorsque vous publiez une modification à partir du DBGrid qui reçoit ses données d'un TAdoQuery, vous verrez que, malheureusement, RowsAffected est zéro. En effet, FRowsAffected de TAdoQuery est mis à jour uniquement lorsque sa méthode ExecSql est appelée et qu'elle n'est pas appelée pour les opérations de jeu de données invoquées via le DBGrid. La différence est que le OnExecuteComplete d'AdoConnection est appelé à partir de l'objet Command utilisé pour exécuter ExecSql de TAdoQuery. Les opérations lancées à partir de DBGrid, otoh, appellent les méthodes de l'objet RecordSet associé à TAdoCustomDataSet dans ses InternalPost et InternalDelete, et qui n'invoque pas le OnExecuteComplete d'AdoConnection.

Les objets RecordSet ont leurs propres ensembles d'événements, voir f.i. RecordSetEvents dans ADOInt.Pas, et vous pouvez concevoir des gestionnaires d'événements partagés pour de manière similaire à l'exemple d'événement AfterPost partagé ci-dessus. Cependant, Je ne pense pas que cela ferait quelque chose d'utile pour vous si vous voulez obtenir la valeur RowsAffected pour un TDataset Insert/Update/Delete invoqué du DBGrid (ou, disons un TDBNavigator connecté à son TDataSource).

La raison pour laquelle je dis que c'est que si vous jetez un coup d'oeil au code source pour la méthode InternalPost du TAdoCustomDataSet vous verrez qu'il comprend

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

et le UpdateData imbriquée fait ses choses par appeler

Recordset.Update(EmptyParam, EmptyParam); 

Maintenant, si vous regardez la documentation MS pour RecordSet.Update, vous verrez par exemple

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

qui stipule clairement que si Update n'affecte pas exactement un enregistrement, une exception est soulevée. J'imagine que c'est ce que @KenWhite avait en tête quand il a dit "Il n'y aura qu'un seul enregistrement mis à jour". Donc, si RecordSet.Update réussit, vous savez qu'une seule ligne a été affectée.

Je n'ai pas vérifié, mais depuis TAdoCustomDataSet.InternalDelete utilise son objet Recordset pour faire la suppression, similaire serait probablement vrai de cela.

+0

merci pour une réponse très bien expliquée. Je vais vérifier ce qui peut être fait dans le projet en sachant que update/insert/edit est exécuté mais ne sait pas RowsAffected. – sddk