Announcement

Collapse
No announcement yet.

Transactions und Designer-Commands

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

  • Transactions und Designer-Commands

    Hallo zusammen,

    vielleicht bin ich ein wenig Blind, jedoch finde ich nicht heraus wie ich für eine Multiuser-Anwendung einem im Abfrage-Konfigurator erstelltem z. B. UPDATE oder DELETE Command eine Transaction zuweisen zu können um entsprechend einen Rowlock via Transaction zu erstellen. Muss ich wirklich alle UPDATE und DELETE - Commands (hier OleDB, Access) "per Hand" als OleDBCommand-Objekt erstellen und ausführen um eine Transaction zuzuweisen oder kann ich den Abfrage-Konfigurator doch nutzen?

    Grüße

    Marcel

  • #2
    Hallo,

    Muss ich wirklich alle UPDATE und DELETE - Commands (hier OleDB, Access) "per Hand" ...
    nein - ab dem .NET Framework 2.0 stehen die Klassen aus dem Namespace System.Transaction zur Verfügung, die als "Klammer" dienen:
    [highlight=C#]
    //
    // Default-Eigenschaften ändern
    //
    TransactionOptions aTO = new TransactionOptions();
    // Transaction Isolation Level READ COMMITED anfordern
    aTO.IsolationLevel = IsolationLevel.ReadCommitted;
    // Timeout-Defaultwert von 60 Sekunden auf 2 Minuten ändern
    aTO.Timeout = new TimeSpan(0, 2, 0);
    //
    // TransactionOptions-Instanz für den Transaction Scope verwenden
    //
    using (TransactionScope aTS = new TransactionScope(TransactionScopeOption.RequiresNe w, aTO))
    {
    using (SqlConnection aConn = new SqlConnection(Properties.Settings.Default.CSTranDB 1))
    {
    sqlCmdMasterInsert.Connection = aConn;
    aConn.Open();
    // ...
    }
    aTS.Complete();
    }
    [/highlight]
    Die Klassen unterstützen sowohl implizite (automatische) als auch explizite (manuelle) Transaktionen. Die Zeitdauer der Gültigkeit eines Transaktions-Kontextes legt auch fest, wann eine Datenbankverbindung wieder für den Datenbankverbindungs-Pool zur Verfügung steht. Solange eine Verbindung noch in einem Transaktions-Kontext steht, legt das Schließen der Verbindung diese nicht sofort in den Pool zurück - dies passiert erst nach dem Freigeben des Transaktions-Kontextes.
    In der Voreinstellung der Klasse SqlConnection wird über den Verbindungszeichenfolgenwert Enlist festgelegt, dass diese automatisch einem zum Zeitpunkt des Öffnens der Datenbankverbindung bestehenden Transaktions-Kontext beitritt. Somit läuft jede neue Datenbankverbindung automatisch im Gültigkeitsbereich der gleichen von TransactionScope kontrollierten Transaktion ab.

    ...hier OleDB, Access....
    Mit dieser Kombination habe ich System.Transaction noch nicht eingesetzt.

    Comment


    • #3
      Hi Andreas,

      nur damit ich das richtig verstehe:

      1) auf diesem Wege kann ich grundsätzlich dem Connection-Objekt eine Transaction mit Isolationlevel usw. zuweisen (damit beim gleichzeitigen Update eines Datensatzes der erste einen Rowlock auslöst bis commit und der zweite entsprechend eine Exception bekommt die ich dann weiterverarbeiten kann, so habe ich das bisher gelöst mit DB's die kein explizites Rowlocking unterstützen)?

      2) Nach nachhaltigem Suchen an diesem Vormittag (und auch schon vorher) ist kein expliziter Rowlock einer Access-DB möglich ausser über Transactions?

      Die Anwendung wird mit c# in VS 2005 entwickelt, die Access-DB beinhaltet nur die Daten. (Kundenanforderung für eine kleine Anwendung, aber multiuserfähig->Konflikte lösen->Record/Row-Lock).

      Wollte halt zur Abwechslung mal soweit es geht den Designer nutzen und all die Automatismen von VS 2005, ich stosse damit halt immer wieder an gewisse Grenzen. Per Hand ohne Designer und Konfigurator ist die Lösung meist etwas aufwendiger jedoch kein Problem.

      Grüße

      Marcel

      Comment


      • #4
        Hallo,

        .. ich stosse damit halt immer wieder an gewisse Grenzen.
        diese werden aber primär nicht von Visual Studio bzw. .NET gesetzt, sondern in diesem Fall von den Fähigkeiten der Microsoft JET Engine als auf dem Anwenderrechner laufender "Motor" für den Zugriff auf die ACCESS-Datenbank.

        ..aber multiuserfähig->Konflikte lösen->Record/Row-Lock.
        Die Kombination ACCESS mit der Mehrbenutzerfähigkeit über echte Datensatzsperren ist bei strenger Betrachtung ein Widerspruch in sich. Die JET Engine puffert den relevanten Datenblock aus der .mdb-Datei im lokalen Arbeitsspeicher und schreibt diesen Block erst in bestimmten Situationen zurück in die .mdb-Datei. Wenn (wie im Fall von ACCESS) der Zugriff auf die .mdb-Datei für jeden Benutzer auf dem eigenen Rechner stattfindet (d.h. der "Motor" läuft nicht zentral auf einem Server), macht nur das optimistische Sperrverfahren einen Sinn. In diesem Fall werden die zu bearbeitenden Datensätze nicht gesperrt, sondern erst beim Speichern der Änderungen (UPDATE) garantiert die WHERE-Einschränkung, dass ein Datensatz nur dann beschrieben wird, wenn in der Zwischenzeit kein anderer Benutzer ein Feld dieses Datensatzes geändert hat. Wenn das UPDATE über die WHERE-Einschränkung ins Leere greift (weil ein Dritter schneller war), kann das eigene Programm folgenden Komfort anbieten:
        1. Der aktuelle Zustand des Datensatzes wird angezeigt, so dass die Änderungen des Dritten sichtbar werden.
        2. Wenn der Anwender trotzdem seine Eingabe speichern will, kann das DataSet über einen Merge-Aufruf den originalen Zustand austauschen, wobei die eigenen Änderungen erhalten bleiben. Der im zweiten Versuch erneut ausgeführte Update-Aufruf schreibt dann die Änderungen erfolgreich in die Datenbank zurück.

        Comment


        • #5
          Hi Andreas,

          genau wie du es beschreibst löse ich es auch noch zusätzlich, die WHERE-Klausel prüft vor einem UPDATE oder DELETE ob der Datensatz überhaupt noch in dem bekannten Zustand vorhanden ist und genau deinen beschriebenen Komfort würde ich dort einbauen.

          Jedoch war ich bisher der vielleicht fälschlichen Auffassung das beim optimistic locking der Fall eintreten kann das 2 Clients ändern in einem Satz(genau gleichzeitig, wahrscheinlichkeit ist zwar nicht hoch aber kann), beide den aktuellen Status mit WHERE abfragen und beide schreiben ihre Änderungen einfach drüber ohne Rückmeldung das der Satz nun anders ist.

          Ich glaubte mit einer Transaction (Readcommited)ein "locken" des Satzes erreichen zu können bis die Transaction abgeschlossen ist. Also bringt mir hier eine Transction für das Editieren oder Löschen auf einen einzelnen Satz gar nix oder macht es nach meiner Beschreibung schon Sinn?

          Gruß

          Marcel

          Comment


          • #6
            Hallo,

            bei einer "echten" SQL-Datenbank ist das optimistische Sperrverfahren garantiert sicher, da nur der auf dem Server installierte SQL Server auf die Datenbankdatei zugreift. Im Fall von ACCESS simuliert jedoch die lokal auf dem Anwender-Rechner installierte JET-Engine die SQL-Fähigkeit. Wenn zwei Anwender gemeinsam auf eine ACCESS-Datenbank zugreifen, die auf einem Netzwerkwerk liegt, dürfen sich die beiden Instanzen der JET-Engine nicht in die Quere kommen, wenn jede die Daten auch lokal puffert. Das Verhalten der ADO.NET-Anwendung wird maßgeblich von dem Verhalten (Konfiguration) der JET Engine bestimmt.

            Also bringt mir hier eine Transction für das Editieren oder Löschen auf einen einzelnen Satz gar nix ...
            Auch früher (zu ADO-Zeiten) war eine pessimistische Sperre einer ACCESS-Datenbank nur dann erfolgreich, wenn bei einem serverseitgen Cursor (adUseServer) und dem Locktype adLockPessimistic ein Feld des Datensatzes sofort beschrieben wurde.

            Comment


            • #7
              Danke Andreas, dies sollte dann mal an dieser Stelle genügen.

              Gruß

              Marcel

              Comment

              Working...
              X