Announcement

Collapse
No announcement yet.

ADO und ACCESS - Zeilenhandles

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

  • ADO und ACCESS - Zeilenhandles

    Hallo,<br>
    vorab: ich verwende den C++Builder5 Enterprise Edition (sollte aber bei meinem Problem mit Delphi5 Enterprise absolut vergleichbar sein), Zugriff auf eine Access97 bzw. Access2000 Datenbank via ADODataSet. Alle Datenzugriffskomponenten werden zur Laufzeit dynamisch erzeigt.
    Eigenschaften eines ADODataSet (beispielhaft: m_DataSet) sind (unter anderem):<br>
    <b> m_DataSet->CommandType = cmdTableDirect;
    m_DataSet->CommandText = m_TableName;
    m_DataSet->CursorType = ctKeyset;
    m_DataSet->CursorLocation = clUseServer;</b><br>
    Die verwendeten Tabellen enthalten (jeweils) mehr als 80.000 Datensaetze - daher auch die (notwendige) Entscheidung fuer <b>clUseServer</b>. Der Zugriff (auf die Datenbank und unterschiedlichste Tabellen) erfolgt sehr schnell und zunaechst auch zuverlaessig (ich verwende hierbei unter anderem auch den <b>->Seek(...)</b> ) - das Problem tritt beim Setzen des aktiven Index auf:<br>
    <b> m_DataSet->IndexName = sAttributeName;</b><br>
    Hier kommt es (soweit ich das Erkennen kann erst beim mehrmaligem Index-Wechsel) zu folgender Fehlermeldung:<br>
    <b> Alle Zeilenhandles müssen freigegeben werden, bevor neue abgerufen werden können.</b><br>
    Was ist mit <b>Zeilenhandles</b> gemeint? Wer reserviert sich die und wie kann ich sie wieder freigeben?<br>
    Ein (ueber eine Datasource) angehangenes DBGrid hatte ich bereits versuchsweise entfernt bzw. DisableControls verwendet - kein Erfolg.
    Natuerlich passieren einige Abfragen von Feldern dieser Tabelle zwischenzeitlich - editiert wird aber nichts.<br>
    Das einzige was hilft ist ein <b>->Close()</b> vor dem setzen des neuen <b>IndexName</b> und dann wieder <b>->Open()</b> - Nur das ist wegen der verlorenen Zeit nicht akzeptabel. Da muss es doch einen besseren Weg geben !?

    Leider komme ich trotz vielen Versuchen nicht weiter und hoffe jetzt auf Eure Hilfe.

    Beste Gruesse<br>
    Stefan

  • #2
    Hallo,

    ich gehe einmal davon aus, das mit "Zeilenhandle" das <b>Row Handle</b> von OLE DB gemeint ist. Im Microsoft Data Access Components 2.5 SDK ist dazu folgendes zu finden:

    <i>The consumer then requests a number of rows from the provider using IRowset::GetNextRows. The provider retrieves the data for these rows and stores it in the data cache. The provider then returns an array of row handles to the consumer. Each row handle returned by the provider has an initial reference count of one. The consumer is then free to get the data for any rows from the provider using GetData. The consumer supplies GetData with the row handle, the handle of an accessor, and the buffer location into which to return the data; the provider copies the data to the location specified by the consumer.
    </i>

    Ich würde zuerst prüfen, ob der Fehler immer dann auftritt, wenn die Zeitspanne zwischen dem Indexwechsel zu kurz ist. Als nächstes würde ich einen Test ohne TADODataset machen und direkt das RecordSet-Objekt von ADO einsetzen. Tritt der Fehler dann immer noch auf, muss er direkt in ADO bzw. im OLE DB-Provider liegen

    Comment


    • #3
      Hallo Andreas Kosch,<br>
      zunächst herzlichen Dank für die schnelle Antwort.<br>
      Ich habe mich in den letzten Tagen coch einmal intensiv mit dem Problem auseinandergesetzt - und siehe da: ich habe einen Weg gefunden wie man's auf einfache Weise nachvollziehen kann.
      (C++Builder5 und Delphi5 zeigen das selbe Verhalten (sprich: kommen zum selben Fehler)!<br><br>
      Man nehme:<br>
      1. Eine ADOConnection<br>
      <b> object ADOConnection1: TADOConnection<br>
      Connected = True<br>
      ConnectionString = <br>
      'Provider=Microsoft.Jet.OLEDB.4.0;Password="";User ID=Admin;Data ' +<br>
      'Source=\\Wskmdeu99dalton\MatSelectDev\Database\Ac tual\Material20' +<br>
      '00.msd;Mode=ReadWrite;Extended Properties="";Jet OLEDB:System da' +<br>
      'tabase="";Jet OLEDB:Registry Path="";Jet OLEDBatabase Password' +<br>
      '="";Jet OLEDB:Engine Type=5;Jet OLEDBatabase Locking Mode=1;Je' +<br>
      't OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transact' +<br>
      'ions=1;Jet OLEDB:New Database Password="";Jet OLEDB:Create Syste' +<br>
      'm Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDBon'#39 +<br>
      't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica' +<br>
      ' Repair=False;Jet OLEDB:SFP=False'<br>
      CursorLocation = clUseServer<br>
      Mode = cmReadWrite<br>
      Provider = 'Microsoft.Jet.OLEDB.4.0'<br>
      Left = 16<br>
      Top = 8<br>
      end</b><br>
      <br><br>
      2. Ein ADODataSet<br>
      <b> object ADODataSet1: TADODataSet<br>
      Active = True<br>
      Connection = ADOConnection1<br>
      CursorLocation = clUseServer<br>
      CommandText = 'DataDescription'<br>
      CommandType = cmdTableDirect<br>
      Parameters = <><br>
      Left = 64<br>
      Top = 8<br>
      end</b><br>
      <br>
      Im Programm führe man dann folgenden Code aus (z.B. beim Click-Ereignis eines Buttons):<br>
      <b> ADODataSet1.IndexName:= 'idDataObj';<br>
      if ( not ADODataSet1.Seek( 3888, soFirstEQ ) ) then<br>
      ShowMessage( 'Nicht gefunden!');</b><br>
      Die Nummer <b>3888</b> ist in der Datenbanktabelle <b>nicht</b> vorhanden! <br>
      Beim ersten Aufruf ist alles in Ordnung: Die MessageBox wird angezeigt. Auch beim zweiten Aufruf sieht alles (noch) normal aus.<br>
      <b>ABER:</b> Alle Versuche jetzt die Property <b>IndexName</b> des <b>ADODataSet1</b> zu setzen (also auch der erneute Aufruf des Codes) führen zum Fehler:
      <b>Alle Zeilenhandles müssen freigegeben werden, bevor neue abgerufen werden können.</b>
      <br>
      Ergebnis meiner Versuche:
      Immer wenn nach einem Seek der Datensatzzeiger am Ende (Eof) oder am Anfang (Bof) zum Stehen kommt (Suche nach nicht vorhandenem Wert mit <b>soFirstEQ</b> oder Suche nach einem Wert kleiner als der kleinste vorhandene mit soBeforeEQ) kann man nach dem zweiten Aufruf eines solchen Suchvorgangs den <b>IndexName</b> nicht mehr setzen.<br>
      Auch zwischendurch Umpositionieren ( z.B. mit <b>First</b> ) hilft nicht!.
      <br><br>
      Sollte dies stimmen, so wäre das natürlich ein <b>ganz fataler</b> Fehler. Nur: wo liegt er (ADO/Delphi/C++Builder) und wie kann man ihn umgehen?
      <br><br>
      Beste Grüße
      Stefa

      Comment


      • #4
        Hallo,

        ich habe heute etwas experimentiert (Delphi 5 UpdatePack#1 + ADO-Patch 1.2.1 Build 3). Bei diesen Experimenten konnte ich das Beispiel nicht nachvollziehen, da ich andere Fehlermeldungen erhalte ;-) <br>
        Bereits beim ersten Aufruf von <b>Seek</b> hagelt es eine Fehlermeldung ("Merkmal wird vom Provider nicht unterstützt"), wobei das Verhalten davon abhängt, ob die MDB-Datei mit ACCESS 2000 entweder in das a) ACCESS97-Format oder b) ACCESS 2000-Format konvertiert wird.

        Ich würde daher vorschlagen, das Projekt mit Debug-DCUs zu compilieren und zeilenweise durch die VCL zu steppen und dabei ein Auge auf die fehlerauslösende Stelle zu werfen

        Comment


        • #5
          Hallo,
          <br>
          <br>
          danke für die Versuche!<br>
          Ich hatte in einer SDK-Quelle gelesen, daß die Seek-Funktionalität tatsächlich nur vom entsprechenden Jet-Provider mit einer Access<b>2000</b> Datenbank unterstützt wird. Mit einer Access<b>97</b> Datenbank kann das (per ADO laut MS) "derzeit" nicht funktionieren.
          <br><br>
          Gruß Stefan Muelhen

          Comment


          • #6
            Hallo,

            aha - und da soll nur noch mal einer über die BDE meckern! Beim Umstieg auf ADO kommt man bei ACCESS-Datenbanken anscheinend vom Regen in die Traufe ;-

            Comment

            Working...
            X