AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Access-Datenbank gesperrt - Problem mit Windows-Update?
Thema durchsuchen
Ansicht
Themen-Optionen

Access-Datenbank gesperrt - Problem mit Windows-Update?

Ein Thema von berens · begonnen am 6. Okt 2020 · letzter Beitrag vom 8. Okt 2020
Antwort Antwort
Delphi.Narium

Registriert seit: 27. Nov 2017
2.589 Beiträge
 
Delphi 7 Professional
 
#1

AW: Access-Datenbank gesperrt - Problem mit Windows-Update?

  Alt 8. Okt 2020, 10:50
Hilfe, soviele Fragen und so richtig kann ich das alles nicht beantworten

Hier erstmal ein Stück Code aus 'nem Programm, das Ado nutzt und auf diverse Datenbanken zugreifen können sollen muss
Delphi-Quellcode:
  // Hier den Datenbanktypen abfragen und die Werte für Cursor ... setzen.
  // CursorLocation bei SQLite muss wohl clUseClient sein,
  // bei Access aber clUseServer
  // Hier noch testen, was bei SQLite am sinnvollsten ist.
  if fDBIsSQLite then begin
    // ctUnspecified, ctOpenForwardOnly, ctKeyset, ctDynamic, ctStatic
    // Diese Variante spart Arbeitsspeicher und ist schnell.
    // Aber es gibt keine RecNo.
    // Änderungen von Datensätzen nicht möglich.
    // con.CursorLocation := clUseServer; // Dann gibt es keine RecNo :-(
    // qrySQL.CursorType := ctKeyset;
    // qrySQL.CursorType := ctStatic;
    // Benötigt viel Arbeitsspeicher, deutlich mehr, als die Datenbankgröße.
    // Ist sehr langsam.
    qrySQL.CursorLocation := clUseClient;
    qrySQL.CursorType := ctDynamic;
    // qrySQL.CursorType := ctStatic;
    // qrySQL.CursorType := ctKeyset;
    dbckOK.ValueChecked := 'T';
    dbckOK.ValueUnchecked := 'F';
  end else
  if fDBIsAccess then begin
    qrySQL.CursorLocation := clUseServer;
    qrySQL.CursorType := ctStatic;
    dbckOK.ValueChecked := 'Wahr';
    dbckOK.ValueUnchecked := 'Falsch';
  end else
  if fDBIsFirebird then begin
    qrySQL.CursorLocation := clUseClient;
    qrySQL.CursorType := ctDynamic;
    dbckOK.ValueChecked := '1';
    dbckOK.ValueUnchecked := '0';
  end else begin
    // Ansonsten?
    qrySQL.CursorLocation := clUseClient;
    qrySQL.CursorType := ctDynamic;
    dbckOK.ValueChecked := '1';
    dbckOK.ValueUnchecked := '0';
  end;
Abhängig vom Datenbanktyp unterscheiden sich die Werte für CursorLocation und CursorType. Ohne diese Unterscheidung gibt es garantiert Fehler (zumindest auf meinen Systemen).

Da das Ganze schon ein paar Jahre alt ist, weiß ich nicht mehr so genau, wie ich zu welchen Werten kam, aber seit dem scheint es rund zu laufen.

Mein Vorgehen wäre von daher zuerst mal mit CursorLocation und CursorType zu experimentieren, bis Dein Testprogramm, das Du zweimal gestartet hast, keinen Fehler mehr wirft oder Du garantiert alle Kombinationen der beiden Eigenschaften "durchhast" und weißt, dass sie alle zu Fehlern führen.

Mit dieser Funktion baue ich mir aus meinen Programmen heraus den Connectionstring auf (sofern wahlweise auf unterschiedliche Datenbanken zugegriffen werden soll).
Delphi-Quellcode:
function fnGetDataSourceString(Handle : THandle;
                               ADOConnection : TADOConnection;
                               sConnection : String = '') : Boolean;
begin
  ADOConnection.Connected := False;
  ADOConnection.ConnectionString := PromptDataSource(handle,sConnection);
  ADOConnection.Connected := True;
  Result := ADOConnection.Connected;
end;
Was kommt bei Deinem Testprogramm dabei raus? Stimmt das mit dem von Dir selbst erstellten Connectionstring überein oder mit dem vom Assistenten generierten? Bei meinen System stimmt es eher mit Deinem (im vorherigen Post) selbst erstellten Connectionstring überein.

Hier ein Beispiel:
Code:
Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;Data Source=C:\Support\TipVerwaltung.mdb;Mode=Share Deny None;Extended Properties="";Jet OLEDB:System database="";Jet OLEDB:Registry Path="";Jet OLEDB:Database Password="";Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False
Querys werden bei mir nach Gebrauch sofort per Close geschlossen. Allerdings erstelle ich sie nicht dynamisch, sondern hab' sie gewöhnlich auf 'nem TDataModule, auch wenn es da durchaus mal eine ganze Reihe für unterschiedliche Zwecke geben kann.

Zur Reihenfolge:

Weise bitte zuerst den Connectionstring zu und ändere erst dann (soweit erforderlich) die Eigenschaften der ADOConnection. Ich gehe mal davon aus, dass die von Dir gesetzten Werte beim Setzen des Connetionstring "überschrieben" werden. Machst Du die Änderungen nach der Zuweisung des Connectionstrings, werden "seine" Werte durch Deine überschrieben. Damit wärst Du dann quasi der Gewinner. So, wie Du es momentan zu machen scheinst, gewinnt jedoch der Connectionstring.

Als erste Idee (ohne Garantie für irgendwas):
Delphi-Quellcode:
    db.Close;
    db.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;'
                       + 'User ID=Admin;'
                       + 'Data Source=' + _FileName + ';'
                       + 'Mode=Share Deny None;'
                       + 'Jet OLEDB:System database="";'
                       + 'Jet OLEDB:Registry Path="";'
                       + 'Jet OLEDB:Database Password="";'
                       + 'Jet OLEDB:Engine Type=5;'
                       + 'Jet OLEDB:Database Locking Mode=1;'
                       + 'Jet OLEDB:Global Partial Bulk Ops=2;'
                       + 'Jet OLEDB:Global Bulk Transactions=1;'
                       + 'Jet OLEDB:New Database Password="";'
                       + 'Jet OLEDB:Create System Database=False;'
                       + 'Jet OLEDB:Encrypt Database=False;'
                       + 'Jet OLEDB:Don''t Copy Locale on Compact=False;'
                       + 'Jet OLEDB:Compact Without Replica Repair=False;'
                       + 'Jet OLEDB:SFP=False;'
                       + 'Persist Security Info=False;';
    db.KeepConnection := True; // HAL_Registry_GetBool('KeepConnection', True);
    db.LoginPrompt := False;
    db.CursorLocation := clUseServer;
    db.CursorType := ctStatic;
    db.IsolationLevel := ilReadCommitted;
    db.Mode := cmReadWrite;

    c1 := db.ConnectionString;
    db.Open;
    c2 := db.ConnectionString;
Damit scheinen bei mir mehrere Instanzen eines Programmes problemlos mit einer Accessdatenbank arbeiten zu können.
  Mit Zitat antworten Zitat
berens

Registriert seit: 3. Sep 2004
441 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Access-Datenbank gesperrt - Problem mit Windows-Update?

  Alt 8. Okt 2020, 11:15
Vielen Dank für die detaillierte Antwort.

Ja, bei mir kommt auch der lange ConnectionString raus, in sofern verwende ich den jetzt auch.

Ich habe all meine Quelltextdatei überarbeitet:
-Es wird nun häufiger eine über Parameter übergebene TAdoConnection verwendet, anstatt selbst (temporär) eine neue zu Erstellen
-Überall wo eine temporäre AdoConnection erstellt wird, gebe ich paranoia-mäßig alles mit try..finally frei
Delphi-Quellcode:
      finally
        CloseQueryAndClearSQLText(q);
      end;
    finally
      db.Close;
    end;
  finally
    FreeAndNil(q);
    FreeAndNil(db);
  end;
Was mich mit deinem Post jetzt aufgeschreckt hat:
Bisher dachte ich, dass cmReadWrite letztendlich doch "Einzel-Benutzung" bedeutet, da das Wort "Share" fehlt. Ich verwende bis dato (imo problemlos?) immer cmShareDenyNone - "Alle Teilen, nichts verbieten". So wurde das glaube ich auch überall empfohlen und in den Beispielen verwendet. Ich bin eben fast vom Hocker gefallen, als ich in der OH nachgeschlagen habe:
Code:
cmReadWrite - Die Verbindung verfügt über Lese-/Schreibrechte.
cmShareDenyRead - Die Verbindung kann von anderen Benutzern nicht mit Leseberechtigung geöffnet werden.
cmShareDenyWrite - Die Verbindung kann von anderen Benutzern nicht mit Schreibberechtigung geöffnet werden.
cmShareDenyNone - Die Verbindung kann mit keiner Art von Zugriffsrecht von anderen Benutzern geöffnet werden.
cmShareDeny... : Der Benutzer kann alles, ausser Read-Lesen, Write-Schreiben, None-Nichts --> Der Benutzer kann alles, mit Ausnahme von nichts - ohne Ausnahme, siehe auch: https://www.delphipraxis.net/107684-post4.html
Zitat:
nein, MSAccess ist auch für einen Mehrbenutzermodus vorgesehen

der Verbindungsstring wird normalerweise mit den Zugangsberechtigungen "share deny none' also jeder kann gleichzeitig zugreifen
s.a. Connection.Mode cmShareDenyNone
Edit: Ebenfalls hier wird rauf gepocht, das cmReadWrite nicht im Netzwerk ausreicht, und cmShareDenyNone zu verwenden ist: https://www.delphipraxis.net/43690-a...ert-nicht.html


Hier bräuchte ich jetzt bitte echt schnell nochmal Rückmeldung:
Was Unterscheidet cmShareDenyNone von cmReadWrite? Ist cmReadWrite wirklich für Mehrbenutzer-Zugriff für Access-Datenbanken über Netzwerk geeignet? Können dabei (z.B. nach einem Update) [einmalig] Tabellen angepasst werden (Spalten hinzufügen, ...), oder schlagen irgendwelche Befehle fehl?
Delphi 10.4 32-Bit auf Windows 10 Pro 64-Bit, ehem. Delphi 2010 32-Bit auf Windows 10 Pro 64-Bit

Geändert von berens ( 8. Okt 2020 um 11:19 Uhr)
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.589 Beiträge
 
Delphi 7 Professional
 
#3

AW: Access-Datenbank gesperrt - Problem mit Windows-Update?

  Alt 8. Okt 2020, 11:41
Ehrlich gesagt: Keine Ahnung.

Habe seinerzeit rumprobiert, bis ich zu dem Schluss kam, dass die oben von mir gepostete Variante (für meine Begriffe) ordentlich funktioniert.

Die Formulierung
Code:
cmShareDenyNone - Die Verbindung kann mit keiner Art von Zugriffsrecht von anderen Benutzern geöffnet werden.
klingt für mich so: Die Anderen dürfen nix.
Aber: Man kann die Formulierung durchaus auch anders interpretieren.

Für mich klingt das so: Egal mit welchen Rechten es die anderen versuchen, sie werden scheitern.

Aber man kann es auch so interpretieren: Egal welche Rechte die Anderen nutzen, sie können zugreifen.

Bei dieser Art von Hilfe bin ich immer hilflos, denn die Aussage entspricht in etwa einem "Entschiedenen sowoh als auch" (oder so ähnlich).

Viele AdoConnection = viele Handles, viele Querys = viele Handles.

Was ich nicht weiß, inwieweit die Handles beim Freigeben der AdoConnections bzw. der Querys sofort "verschwinden".

Von daher ist mein Vorgehen immer so:

Alles, was ich brauche, wird bereits in der Entwicklungsumgebung auf's Formular ... gepappt. Dabei gilt: Von allem so wenig wie möglich.

Mehrere AdoConnetions nur, wenn auch mehrere Datenbanken genutzt werden. Pro DB nur eine Connection.

Querys: Eine für Abfragen, eine für Insert, Update, Delete ... (also den Rest) (ggfls. pro DB).

Pro DBGrid, DBCtrlGrid, DataSource (o. ä.) (sofern welche zum Einsatz kommen) eine Query.

Connections verbinden sich beim Programmstart mit der Datenbank und beenden die Verbindung beim Programmende. Auch hier gilt: So wenig wie möglich.

Ob dieses Vorgehen nun den Regeln der Kunst entspricht, mit irgendwelchen Vorgehensmodellen, ... konform geht, keine Ahnung. Fahre mit diesem Vorgehen seit fast 2 Jahrzehnten gut und solange läuft auch schon ein Teil meiner Software ohne Mucken.

Geändert von Delphi.Narium ( 8. Okt 2020 um 11:42 Uhr) Grund: Schreibfehler
  Mit Zitat antworten Zitat
Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.684 Beiträge
 
Delphi 5 Professional
 
#4

AW: Access-Datenbank gesperrt - Problem mit Windows-Update?

  Alt 8. Okt 2020, 12:30
Vielleicht lohnt sich ein Blick auf die Englische Erklärung:
Connect ModeMeaning
cmUnknownPermissions are not yet set for the connection or cannot be determined.
cmReadRead-only permissions are available to the connection.
cmWriteWrite-only permissions are available to the connection.
cmReadWriteRead/write permissions are available to the connection.
cmShareDenyReadPrevents others from opening connections with read permissions.
cmShareDenyWritePrevents others from opening connection with write permissions.
cmShareExclusivePrevents others from opening connection.
cmShareDenyNonePrevents others from opening connection with any permissions.
Klingt für mich danach, als müsste man cmShareDenyNone als cmShareDenyAll, cmShareDenyAny oder cmShareDenyEverything deuten. Und ich frage mich, was dann noch der Unterschied zwischen cmShareDenyNone und cmShareExclusive sein soll.

Sorry, wenn der Beitrag nicht (sonderlich) hilfreich gewesen sein sollte.

Grüße
Dalai
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.589 Beiträge
 
Delphi 7 Professional
 
#5

AW: Access-Datenbank gesperrt - Problem mit Windows-Update?

  Alt 8. Okt 2020, 12:55
Dein Beitrag besagt genau das, was ich vermute.

cmShareDenyNone = Außer mir darf keiner was.

Geändert von Delphi.Narium ( 8. Okt 2020 um 12:57 Uhr) Grund: Fehler behoben
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:14 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz