Announcement

Collapse
No announcement yet.

ADO und BDE TUpdateObject

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • ADO und BDE TUpdateObject

    Hallo,

    Nochmal zum Thema Zugriff auf mehrere Tabellen im ADODataSet.

    Nach meinen bisherigen Erfahrungen gibt es anscheinend keine Möglichkeiten sauber eine mit einem JOIN erzeugte Abfrage zurückzuschreiben. Bei der BDE hatte ich ja die volle Steuerung über das TUpdateObject in der Hand.
    Wie soll ich aber mit ADO umgehen, wenn in der Abfrage zwei Tabellen verküpft sind, die eine bestimmte Reihenfolge beim Anlegen neuer Sätze verlangen. Im Buch "ASP
    Programmierung mit ADO" wird der Hinweis gegeben mit UpdateBatch und
    "Unique Table" zu arbeiten. Wie soll man das aber machen, wenn die Daten in einem Grid dargestellt werden. Der Nutzer kann in jeder beliebigen Spalte (Tabelle) Eingaben machen.
    Es ist also nicht sicher gestellt welche Tabelle ADO wirklich zuerst bearbeitet.

    Das Beispiel von Andreas Kosch "EDITJOIN" der Entwicklerkonferenz vom Februar hat mir auch nicht weiter geholfen. Man kann zwar einzelne Dateninhalte ändern, doch das Anlegen neuer Zeilen führt zur Exception.

  • #2
    Hallo,

    in meinem Beispielprojekt EDITJOIN kann man <br>
    a) Daten der Master-Tabelle ändern <br>
    b) Daten der Detail-Tabelle ändern <br>
    c) Neue Datensätze der Detail-Tabelle hinzufügen

    Das Prinzip wird deutlicher, wenn man den Aufbau minimiert, wie das folgende Beispiel demonstriert:
    <b>Inhalt der DFM-Datei</b>:
    <pre>
    object Form1: TForm1
    Left = 192
    Top = 107
    Width = 696
    Height = 480
    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 DBNavigator1: TDBNavigator
    Left = 16
    Top = 56
    Width = 320
    Height = 25
    DataSource = DataSource1
    TabOrder = 0
    end
    object DBGrid1: TDBGrid
    Left = 16
    Top = 88
    Width = 321
    Height = 193
    DataSource = DataSource1
    TabOrder = 1
    TitleFont.Charset = DEFAULT_CHARSET
    TitleFont.Color = clWindowText
    TitleFont.Height = -11
    TitleFont.Name = 'MS Sans Serif'
    TitleFont.Style = []
    end
    object ButtonReOpen: TButton
    Left = 152
    Top = 16
    Width = 75
    Height = 25
    Caption = 'ReOpen'
    TabOrder = 2
    OnClick = ButtonReOpenClick
    end
    object ADOConnection1: TADOConnection
    Connected = True
    ConnectionString =
    'Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initi' +
    'al Catalog=OSSISOFT;Data Source=(local);Use Procedure for Prepar' +
    'e=1;Auto Translate=True;Packet Size=4096;Workstation ID=Solo9150' +
    'P323;Use Encryption for Data=False;Tag with column collation whe' +
    'n possible=False'
    LoginPrompt = False
    Provider = 'SQLOLEDB.1'
    Left = 16
    Top = 16
    end
    object ADODataSet1: TADODataSet
    Active = True
    Connection = ADOConnection1
    CursorType = ctStatic
    AfterOpen = ADODataSet1AfterOpen
    CommandText =
    'SELECT m.ID,m.Name,d.MasterID,d.eMail '#13#10'FROM TBL_MASTER m JOIN T' +
    'BL_DETAIL d ON d.MasterID = m.ID '#13#10'ORDER BY m.Name'
    Parameters = <>
    Left = 56
    Top = 16
    object ADODataSet1ID: TAutoIncField
    DisplayWidth = 5
    FieldName = 'ID'
    ReadOnly = True
    end
    object ADODataSet1Name: TStringField
    DisplayWidth = 10
    FieldName = 'Name'
    Size = 50
    end
    object ADODataSet1MasterID: TIntegerField
    DisplayWidth = 8
    FieldName = 'MasterID'
    end
    object ADODataSet1eMail: TStringField
    DisplayWidth = 20
    FieldName = 'eMail'
    Size = 50
    end
    end
    object DataSource1: TDataSource
    DataSet = ADODataSet1
    Left = 88
    Top = 16
    end
    end
    </pre>
    <b>Ereignisbehandlungsmethode</b>:
    <pre>
    procedure TForm1.ADODataSet1AfterOpen(DataSet: TDataSet);
    begin
    ADODataSet1.Properties['Unique Table'].Value := 'TBL_DETAIL';
    end;
    </pre>
    Das Programm definiert die Eigenschaft <b>Unique Table</b>, so dass die Detail-Tabelle als primäres Ziel definiert wird. Im MDAC-SDK liest sich das dann so: "<i>ADO dynamic properties exist to give explicit control to Row Fix-up functionality. When the Unique Table ADO property is set, Row Fix-up mode is implemented. The Unique Table property restricts INSERT, UPDATE, and DELETE statements affecting the Unique Table. Columns of the base tables are updatable, but those columns not in the Unique Table cannot be included in any update method.</i>

    Comment


    • #3
      Hallo,

      das ist schon ganz schön und gut. Es beantwortet meine Frage nur teilweise.
      Ein Ersatz für das TUpdateObject gibt es anscheinend nicht. Mit anderen Worten, kann ich einen vollständig editierbaren bzw erweiterbaren Join in eine Dataset bearbeiten?

      Es also nicht möglich einen Konstrukt zu schaffen in dem ich die Master-Table ebenfalls erweitern kann

      Comment


      • #4
        Hallo,

        das Grundproblem betrifft den C/S-Glaubenskrieg <i>Fat Client vs. Fat Server</i>. Anstellen nach einem Weg zu suchen, wie die BDE/IBX-Implementierung 1:1 in ADO nachgebaut werden kann, würde ich einen Weg suchen, wie die Aufgabe möglichst einfach gelöst werden kann. Und diese würde - am Beipspiel einer <i>SQL Server 2000</i>-Datenbank - so aussehen: <br>
        a) VIEW in der Datenbank: TADODataSet muss keinen JOIN verwenden <br>
        b) INSTEAD OF-Trigger in der Datenbank: Der VIEW ist editierbar.<br>
        In diesem Fall wird die komplette Logik (Wann müssen welche Tabellen in welcher Reihenfolge angefasst werden?) in den Trigger gelegt, da von dort aus über die virtuelle Tabelle <i>Inserted</i> alle gesuchten Infos zur Verfügung stehen. Der Trigger kann ermitteln, welche Felder überhaupt geändert wurden und dann entsprechend darauf reagieren.

        Wenn alles jedoch auf dem Client ablaufen soll, gibt es auch mehrere Möglichkeiten:

        1. Neuen Master-Datensatz über die RecordSet-Methode <b>AddNew</b> anlegen, wobei dort bereits die Spalten und Werte exakt definiert werden. ADO schreibt den Datensatz direkt in die Tabelle, ohne in den Edit-Modus zu wechseln.

        2. Alle Eingaben im <b>ltBatchOptimistic</b>-Modus durchführen. Anstelle jedoch <b>UpdateBatch</b> aufzurufen, wird folgendes gemacht: <br>
        a) RecordSet clonen: aCloneRS := ADODataSet1.Recordset.Clone(adLockUnspecified); <br>
        b) Clone filtern: aCloneRS.Filter := adFilterPendingRecords<br>
        Der Clone zeigt nun nur die geänderten Datensätze an, so dass man nun entsprechend je vorgefundener Änderung im eigenen Programm reagieren kann.<br>
        c) <b>CancelBatch</b> setzt nach dem Update (Clone) das originale RecordSet zurüc

        Comment

        Working...
        X