|
Datenmenge klonen
Frage: Ab Delphi 7 kann die Methode Clone direkt über die VCL aufgerufen werden. Nach dem Clonen müssen nun noch die Calc- und Lookupfields vom SourceDataSet in das CloneDataSet übertragen werden. Wie macht man das?
Antwort: Es wird eine Lösung für ein Problem gesucht, das gar nicht existiert! Die berechneten Spalten tauchen nur in der VCL-Welt (genau gesagt in TADODataSet) auf, das als Datenquelle darunterliegende Recordset-Objekt hat davon allerdings keine Ahnung. Daher sind nach dem Klonen der Datenmenge auch keine weiteren Aktionen notwendig, wie das folgende Beispiel demonstriert. Um das Beispiel nachzuvollziehen, sind die folgenden Schritte notwendig:
1. Beispieltabelle im MS SQL Server anlegen
2. TADOConnection und das originale TADODataSet konfigurieren, dabei die berechnete Spalte über den Feldeditor von Delphi zusätzlich anlegen
3. Ereignisbehandlungsmethode für OnCalcFields einrichten
4. Die fertig konfigurierte TADODataSet-Instanz über die Zwischenablage "klonen" und bei dem Klone die Verbindung zur Datenbank entfernen (d.h. die Eigenschaft Connection wird im Objektinspektor geleert). Der TADODataSet-Klon kann somit niemals auf die originale Datenbank-Tabelle zugreifen, sondern ist darauf angewiesen, vom Programm eine bereits gefüllte Datenmenge (Recordset-Objektinstanz) zu erhalten.
5. Der zweiten TADODataSet-Instanz eine eigene Ereignisbehandlungsmethode für OnCalcFields zuweisen
6. Zur Laufzeit der zweiten TADODataSet-Instanz die geklonte Recordset-Instanz unterschieben.
Schritt 1: Vorbereitung der Datenbank
USE tempdb
GO
CREATE TABLE CalcDemo
(
RecID INTEGER NOT NULL IDENTITY PRIMARY KEY,
Value1 INTEGER NOT NULL,
Value2 INTEGER NOT NULL
)
GO
INSERT INTO CalcDemo (Value1,Value2) VALUES (2,3)
INSERT INTO CalcDemo (Value1,Value2) VALUES (3,4)
INSERT INTO CalcDemo (Value1,Value2) VALUES (4,5)
INSERT INTO CalcDemo (Value1,Value2) VALUES (5,6)
GO
Schritt 2: Programm
Beim Anklicken des Buttons wird die Datenmenge geklont und der zweiten TADODataSet-Instanz untergeschoben, die ebenfalls über die Zwischenablage von der ersten Instanz "geklont" wurde: Beide TDBGrid-Instanzen zeigen die korrekten Daten in der berechneten Spalte an, obwohl es diese Spalte im gefüllten Recordset überhaupt nicht gibt.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, ADODB, Grids, DBGrids, StdCtrls;
type
TForm1 = class(TForm)
DBGrid1: TDBGrid;
ADOConnection1: TADOConnection;
ADODataSet1: TADODataSet;
DataSource1: TDataSource;
ADODataSet1RecID: TAutoIncField;
ADODataSet1Value1: TIntegerField;
ADODataSet1Value2: TIntegerField;
ADODataSet1CalcValue1Value2: TIntegerField;
ButtonClone: TButton;
ADODataSetCloneWithCalcField: TADODataSet;
AutoIncField1: TAutoIncField;
IntegerField1: TIntegerField;
IntegerField2: TIntegerField;
IntegerField3: TIntegerField;
DBGrid2: TDBGrid;
DataSourceClone: TDataSource;
procedure ADODataSet1CalcFields(DataSet: TDataSet);
procedure ButtonCloneClick(Sender: TObject);
procedure ADODataSetCloneWithCalcFieldCalcFields(DataSet: TDataSet);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{ *.dfm}
uses ADOInt;
procedure TForm1.ADODataSet1CalcFields(DataSet: TDataSet);
begin
ADODataSet1CalcValue1Value2.Value := ADODataSet1Value1.Value *
ADODataSet1Value2.Value;
end;
procedure TForm1.ButtonCloneClick(Sender: TObject);
var
aCloneRS : RecordSet;
begin
aCloneRS := ADODataSet1.Recordset.Clone(adLockUnspecified);
ADODataSetCloneWithCalcField.Recordset := aCloneRS;
ADODataSetCloneWithCalcField.Active := True;
end;
procedure TForm1.ADODataSetCloneWithCalcFieldCalcFields(DataSet: TDataSet);
begin
IntegerField3.Value := IntegerField1.Value *
IntegerField2.Value;
end;
end.
Konfiguration des Formulars im Objektinspektor:
object Form1: TForm1
Left = 192
Top = 114
Width = 870
Height = 640
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object DBGrid1: TDBGrid
Left = 8
Top = 8
Width = 377
Height = 113
DataSource = DataSource1
TabOrder = 0
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
end
object ButtonClone: TButton
Left = 96
Top = 200
Width = 75
Height = 25
Caption = 'Clone'
TabOrder = 1
OnClick = ButtonCloneClick
end
object DBGrid2: TDBGrid
Left = 8
Top = 240
Width = 377
Height = 120
DataSource = DataSourceClone
TabOrder = 2
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
end
object ADOConnection1: TADOConnection
Connected = True
ConnectionString =
'Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security In' +
'fo=False;Initial Catalog=tempdb;Data Source=(local)'
LoginPrompt = False
Provider = 'SQLOLEDB.1'
Left = 120
Top = 64
end
object ADODataSet1: TADODataSet
Active = True
Connection = ADOConnection1
CursorType = ctStatic
OnCalcFields = ADODataSet1CalcFields
CommandText = 'select RecID, Value1, Value2 from CalcDemo'
Parameters = <>
Left = 160
Top = 64
object ADODataSet1RecID: TAutoIncField
FieldName = 'RecID'
ReadOnly = True
end
object ADODataSet1Value1: TIntegerField
FieldName = 'Value1'
end
object ADODataSet1Value2: TIntegerField
FieldName = 'Value2'
end
object ADODataSet1CalcValue1Value2: TIntegerField
FieldKind = fkCalculated
FieldName = 'CalcValue1Value2'
Calculated = True
end
end
object DataSource1: TDataSource
DataSet = ADODataSet1
Left = 192
Top = 64
end
object ADODataSetCloneWithCalcField: TADODataSet
CursorType = ctStatic
OnCalcFields = ADODataSetCloneWithCalcFieldCalcFields
CommandText = 'select RecID, Value1, Value2 from CalcDemo'
Parameters = <>
Left = 48
Top = 296
object AutoIncField1: TAutoIncField
FieldName = 'RecID'
ReadOnly = True
end
object IntegerField1: TIntegerField
FieldName = 'Value1'
end
object IntegerField2: TIntegerField
FieldName = 'Value2'
end
object IntegerField3: TIntegerField
FieldKind = fkCalculated
FieldName = 'CalcValue1Value2'
Calculated = True
end
end
object DataSourceClone: TDataSource
DataSet = ADODataSetCloneWithCalcField
Left = 88
Top = 296
end
end
|