Announcement

Collapse
No announcement yet.

Mehrbenutzerkonflike in Datenbankanwendung (Andreas Kosch)

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

  • Mehrbenutzerkonflike in Datenbankanwendung (Andreas Kosch)

    Hallo zusammen,
    ich habe eine Frage bezüglich Mehrbenutzerkonflikte in Datenbankanwendungen.
    Ich arbeite mit Ado.net DataSet und Ms sql 2000
    Es gibt ein Form darunter liegen zwei Tabellen Master und Slawe was für Benutzer natürlich absolut Transparent ist.

    In der Master Tabelle habe ich eine Spalte von Typ TimeStamp, mit deren Hilfe wird festgestellt ob Veränderungen an dem jeweiligen Datensatz stattgefunden haben oder nicht und gegebenenfalls wird eine DBConcurrencyException ausgelöst.
    Das Problem bereitet aber die Slawe Tabelle sie kann mehrere Paare von MasterPK und anderen Tabelle beinhalten und in der Slawe Tabelle gibt es Update als solches nicht. Da können die Paare entweder eingefügt oder gelöscht werden. Das heißt dort nützt mir die Lösung über eine TimeStamp Spalte gar nicht. Ich muss es wohl irgendwie über Time Stampe Spalte in Master Tabelle versuchen das zu regeln. Ich habe ein Trigger für die Slawe Tabelle geschrieben der beim einfügen oder löschen von Datensätzen in Slawe Tabelle den Wert von Time Stampe Spalte in Master Tabelle verändert. So weit so gut, aber da die Werte zu erst in Slawe und dann in Master Tabelle gelöscht werden kriege ich jetzt immer DBConcurrencyException obwohl das gar nicht stimmt.
    Vielleicht weist jemand ein Rat?

    Die Idee mit TimeStamp kam von dot.net Magazin Ausgaben 09.04, 10.04 Autor Andreas Kosch

    Danke

  • #2
    Hallo,

    wenn ich es richtig verstanden habe, soll die Anwendung erkennen, wenn ein anderer Benutzer den Inhalt der Slave-Tabelle geändert hat (neuer Datensatz oder gelöschter Datensatz). Ein Update des Master-Datensatzes soll nur dann erfolgreich sein, wenn <br>
    a) der Master-<b>Datensatz</b> nicht von einem anderen geändert wurde (TIMESTAMP-Prüfung), und <br>
    b) die Slave-<b>Tabelle</B> nicht von einem anderen geändert wurde.

    Die Aufgabe lässt sich über einen Trigger umsetzen, allerdings muss dieser die TIMESTAMP-Spalte in einer <b>zusätzlichen</b> Hilfstabelle füllen. Diese Hilfstabelle hat nur einen Datensatz, in dem der letzte Schreibzugriff auf die Slave-Tabelle vermerkt wird.

    Wenn der Trigger aber statt dessen direkt die Master-Tabelle aktualisiert, hat der Client einen falschen TIMESTAMP-Wert, so dass beim UPDATE die WHERE-Einschränkung nicht mehr passt, wenn ein Dritter in der Zwischenzeit die Slave-Tabelle geändert hat

    Comment


    • #3
      Hallo,
      wie soll die InsertCommand von Slave Tabelle aussehen, denn bevor in Slave etwas eingetragen wird muss es überprüft werden ob der TimeStampAttribut in der Hilfstabelle sich verändert hat oder nicht.
      In der Hilfstabelle trage ich für jeden Datensatz aus Master eine Zeile.
      Slave ist die Auflösungstabelle für n zur m Beziehung zwischen Master und Stammtabelle
      Master-Slave-StammTabelle
      Master(MasterPK, Attribut1,TimestampAttribut)
      Slave(SlavePK, MasterFK,XFK)
      StammTabell(StammTabellePK,Attribut1,Attribut2)
      Hilfstabelle(MasterPK, Attribut, TimestampAttribut)
      PK=Primary Key
      FK=Foreign Key
      Vielleicht muss auch die SelectCommand entsprechend ahngepasst werden?
      Für die konkreten Vorschläge würde ich Dankbar sei

      Comment


      • #4
        Hallo,

        &gt;..wie soll die InsertCommand von Slave Tabelle aussehen..

        wenn für diese Aufgabe eine Stored Procedure verwendet wird, kann diese alle Prüfungen vorab vornehmen. Beim SELECT muss sich der Client den aktuellen Timestamp-Wert als der Hilfstabelle holen, um diesen später beim Update als zusätzlichen Parameter an die Stored Procedure übergeben zu können

        Comment


        • #5
          Hallo,
          ich bekomme die Timestamp-Wert aus der Hilfstabelle nicht.
          So sieht meine SelectCommand

          Select SlavePK,MasterFK,XFK,tsp from Slave join Hilfstabelle on (Slave.MasterFK=Hilfstabelle.MasterPK)

          In Query Analyser siet gut aus, aber bei der InserCommand habe ich mit Debugger angeschaut die tsp hatte Wert DBNull.
          Dann habe ich die StoredProcedure geschrieben, aber wird sie den DBConccurencyException auslösen? Den in Query Analyser wenn gibt sie keine Fehlermeldung aus.
          So sieht die SP aus
          CREATE PROCEDURE InsertSlave
          @MasterFK int,
          @XFK int,
          @Original_tsp Timestamp,
          @SlavePK int OUT,
          @tsp Timestamp OUT

          AS
          Declare @tspC Timestamp

          Set @tspC=(select tsp from Hilfstabelle where MasterPK=@MasterFK)
          if (@tspC=@Original_tsp)
          Begin
          INSERT INTO Slave (MasterFK, XFK)
          VALUES(@MasterFK, @XFK)
          SET @SlavePK = SCOPE_IDENTITY()
          Set @tsp=(Select tsp from Hilfstabelle where MasterPK=@MasterFK)
          End
          Dank

          Comment


          • #6
            Hallo,

            &gt;..ich bekomme die Timestamp-Wert aus der Hilfstabelle nicht.

            die Hilfstabelle soll jede Änderungen an der Slave-Tabelle erkennen, also auch, ob ein Datensatz neu hinzugefügt, geändert oder gelöscht wurde. Die Hilfstabelle speichert somit nur einen Datensatz (genauer gesagt, nur einen einzigen Timestamp-Wert). Daher kann der Timestamp-Wert aus der Hilfstabelle nicht über einen JOIN ermittelt werden. Neben einer Batch-SELECT-Abfrage könnte auch eine Stored Procedure diese Daten mit übergeben:
            <pre>
            USE tempdb
            <b>GO</b>
            <br>
            <b>CREATE</b> <b>TABLE</b> Slave(
            SlavePK <b>INTEGER</b> <b>NOT</b> <b>NULL</b> <b>PRIMARY</b> <b>KEY</b>,
            MasterFK <b>INTEGER</b> <b>NOT</b> <b>NULL</b>,
            <b>Value</b> <b>INTEGER</b>)
            <b>GO</b>
            <br>
            <b>CREATE</b> <b>TABLE</b> SlaveHelper (
            recid <b>INTEGER</b> <b>NOT</b> <b>NULL</b> <b>PRIMARY</b> <b>KEY</b>,
            ts ROWVERSION)
            <b>GO</b>
            <br>
            -- Testdaten einfügen
            <b>INSERT</b> <b>INTO</b> Slave <b>VALUES</b> (1,2,3)
            <b>GO</b>
            <b>INSERT</b> <b>INTO</b> SlaveHelper (recid) <b>VALUES</b> (1)
            <b>GO</b>
            <br>
            -- Stored <b>Procedure</b> ermittelt die Daten + <b>Timestamp</b> der Hilfstabelle
            <b>CREATE</b> <b>PROCEDURE</b> spSelectSlave(
            @SlavePK <b>INTEGER</b>,
            @<b>Value</b> <b>INTEGER</b> <b>OUTPUT</b>,
            @ts ROWVERSION <b>OUTPUT</b>)
            <b>AS</b>
            <b>SELECT</b> @ts = ts <b>FROM</b> dbo.SlaveHelper <b>WHERE</b> recid = 1
            <b>SELECT</b> @<b>Value</b> = <b>Value</b> <b>FROM</b> dbo.Slave <b>WHERE</b> SlavePK = @SlavePK
            <b>GO</b>
            <br>
            -- Stored <b>Procedure</b> testen
            <b>DECLARE</b> @<b>Value</b> <b>INTEGER</b>
            <b>DECLARE</b> @ts ROWVERSION
            <b>EXEC</b> spSelectSlave 1, @<b>Value</b> <b>OUTPUT</b>, @ts <b>OUTPUT</b>
            PRINT <b>CAST</b>(@<b>Value</b> <b>AS</b> <b>VARCHAR</b>) + <font color="#9933CC">' - '</font> + <b>CAST</b>(<b>CAST</b>(@ts <b>AS</b> BIGINT) <b>AS</b> <b>VARCHAR</b>)
            </pre&gt

            Comment

            Working...
            X