2016-05-13 17 views
2

wenn ich eine Abfrage wieExecuteCompleted von ADOConnection nicht, wenn der Benutzer Änderungen von Daten über DBGrid gefeuert

Update Table Set aField = 1 Where tablePk = 1 

ich kann erhalten die betroffenen Datenanzahl (RecordsAffected Parameter) von ExecuteComplete Fall AdoConneciton auszuführen. Wenn ich Daten über dbgrid ändere, wird das ExecuteComplete-Ereignis nicht ausgelöst.

Wie kann ich die Anzahl der betroffenen Datensätze nach dem Befehl insert/update/delete erhalten, der von dbgrid ausgeführt wurde?

+1

Verwenden Sie das AfterPost-Ereignis der ADOQuery oder ADOTable, die an das DBGrid angeschlossen ist. Es wird nur ein einzelner Datensatz aktualisiert, so dass Sie die Anzahl im Voraus wissen. –

+0

@KenWhite, das Projekt enthält ca. 100 Adoquery, die an dbGrids angehängt sind. Ich wollte es mit der Verbindung machen, aber es scheint, dass es unmöglich ist. – sddk

Antwort

4

Ich glaube nicht, gibt es eine Möglichkeit, die Anzahl der betroffenen Zeilen zu erhalten, wenn Sie Aktualisierungen vornehmen, fügt und löscht über ein TDBgrid oder andere DB-fähige Komponenten wie TDBNavigator. Der Grund dafür ist, dass DB-sensible Steuerelemente die Methoden Post und Delete von TDataSet und die Aufrufe von Overrides von InternalPost und InternalDelete in TAdoCustomDataSet aufrufen. Sie arbeiten auf eine grundlegend andere Weise als das Ausführen einer SQL-Anweisung über die ExecSql-Methode von beispielsweise TAdoQuery.

TDataSet.Post und TDataSet.Delete sollten nur eine einzelne Zeile betreffen. Wenn der Vorgang erfolgreich ist, wissen Sie also, dass genau eine Zeile betroffen war.

Es ist erwähnenswert, wenn auch nicht viel Hilfe für das, was Sie tun wollen, dass es ist ein Weg, um die gleiche Ereignishandler zu einer Reihe von TAdoCustomDataSet Nachkommen anschließen, die einen TADOConnection teilen, wie in diesem Code gezeigt:

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; 

natürlich, wenn die beteiligten Datensätze bereits ihre eigenen Event-Handler haben, Sie würden eine gewisse Struktur müssen die vorhandenen Handler und Kette das Recht einer von ihnen in dem gemeinsam genutzten Handler (fi TForm1.AfterPost speichern über).

Wenn Sie den obigen Code versuchen und beobachten, was passiert, wenn Sie bearbeitet von dem DBTabelle Post, die ihre Daten von einem TADOQuery bekommt, werden Sie, dass leider sehen, ist die RowsAffected Null. Das liegt daran, dass die FRowsAffected-Funktion von TAdoQuery nur aktualisiert wird, wenn die ExecSql-Methode aufgerufen wird. Sie wird nicht für Dataset-Operationen aufgerufen, die über DBGrid aufgerufen werden. Der Unterschied liegt darin, dass die AdoConnection OnExecuteComplete von dem Objekt Command aufgerufen wird, das TAdoQuery ExecSql ausgeführt wird. Von dem DBGrid, otoh, initiierte Operationen rufen Methoden des RecordSet Objekts auf, das dem TAdoCustomDataSet in seinem InternalPost und InternalDelete, zugeordnet ist, und das AdoConnection OnExecuteComplete nicht aufruft. Die Objekte RecordSet haben ihre eigenen Ereignisse, siehe f.i. RecordSetEvents in ADOInt.Pas, und möglicherweise könnten Sie gemeinsam genutzte Event-Handler für diese in ähnlicher Weise wie die gemeinsame AfterPost Beispiel oben einrichten. Aber Ich denke nicht, dass das etwas nützliches für Sie tun würde, wenn Sie den RowsAffected-Wert für ein TDataset einfügen/aktualisieren/löschen von DBGrid erhalten möchten (oder sagen, ein TDBNavigator verbunden mit seiner TDataSource).

Der Grund, warum ich sagen, dass ist, dass, wenn Sie für die InternalPost Methode des TAdoCustomDataSet einen Blick auf den Quellcode nehmen werden Sie sehen, dass es

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

und die verschachtelte UpdateData hat seine Sachen enthält durch Rufen Sie

Recordset.Update(EmptyParam, EmptyParam); 

Nun, wenn Sie die MS-Dokumentation für RecordSet.Update betrachten, sehen Sie z

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

die klar, dass, wenn Update heißt es nicht genau einen Datensatz nicht beeinflusst, eine Ausnahme ausgelöst. Ich stelle mir vor, dass @KenWhite im Sinn hatte, als er sagte "Es wird nur einen einzigen Datensatz aktualisiert". Wenn RecordSet.Update erfolgreich ausgeführt wird, wissen Sie, dass nur eine Zeile betroffen war, .

Ich habe nicht überprüft, aber da TAdoCustomDataSet.InternalDelete sein Recordset Objekt verwendet, um die Löschung zu tun, würde das wahrscheinlich wahr sein.

+0

danke für sehr gut erklärt antwort. Ich werde überprüfen, was im Projekt getan werden kann, indem ich weiß, dass update/insert/edit ausgeführt, aber RowsAffected nicht bekannt ist. – sddk