PDA

Vollständige Version anzeigen : DS sperren


Forza SGD
03.05.2011, 18:17
Hallo zusammen,

Ausgangspunkt meinen Problems ist ein Formular, auf welchem den Nutzer den Namen eines Mitarbeiters auswählt - hat er dies getan öffnet sich ein weiteres Formular was alle diesem Mitarbeiter zugeschlüsselten Datensätze anzeigt. Da mehrere User gleichzeitig zugreifen hätte ich gern dass wenn ein weiterer nutzer den gleichen Namen wählt das Formular mit den entsprechenden datensätzen nicht angezeigt wird und mittel Msgbox darauf verwiesen wird, das der Mitarbeiter bereits in bearbeitung ist.

Leider funktioniert meine Lösung nicht ganz:

Mittels eines Recordsets sollen Alle Ds den gewählen Mitarbeiter selektiert werden und dann soll geschaut werden ob irgendeiner dieser DS gerade in Bearbeitung ist:

Private Sub cmd_rsc_markierte_kunden_anzeigen_Click()

Dim rst As DAO.Recordset
Dim strSQL As String

strSQL = "SELECT * From tbl_basis_kunden WHERE aq_ad_ma_nr = " & Me.cbo_rsc_auswahl_ad

Set rst = CurrentDb.OpenRecordset(strSQL)

Do
If rst.EditMode <> adEditNone Then
Call MsgBox("Der von Ihnen gewählte AD wird bereits bearbeitet!", vbInformation, "Meldung")
GoTo Exit_Sub
End If
rst.MoveNext
Loop While Not rst.EOF

Exit_Sub:

rst.Close
Set rst = Nothing

Exit Sub


End Sub


Vielleicht liegt es an adEditNone - was ich anstrebe ist, dass sobald dieser DS irgendwo angezeigt wird - soll die Fehlermeldung erscheinen!


Besten Dank schonmal

fraeser
03.05.2011, 18:54
Erstelle doch einfach eine neue Spalte 'in_Bearbeitung' (BIT). Wenn der entsprechende Datensatz (Mitarbeiter) ausgewählt wird, stellst Du den Wert auf TRUE. Erst nach Beendigung der Bearbeitung wieder aus FALSE. Will jemand anderes diesen DS bearbeiten, fragst Du den Wert voher ab (TRUE > Bearbeitung nicht möglich...)

Forza SGD
04.05.2011, 13:14
Hallo fraeser,

Danke für die Antwort, ich werds mal so machen - aber gibt es eine Möglichkeit, in Anlehnung an meine Lösung, um herauszufinden ob ein DS gerade abgefragt bzw. in einem Formular dargestellt wird?

fraeser
04.05.2011, 14:09
In Deinem Beispiel aus #1 müsste die Konstante doch dbEditNone lauten (statt adEditNone).
Vielleicht probierst Du das noch mal....

Forza SGD
04.05.2011, 14:30
Grüß dich,

hast recht - is ja DAO. Ergebnis ist aber leider das gleiche. Aber ich glaube das EditMode auch nicht das richtige ist - wenn ich mittels eines anderen accounts auf die DB zugreife und die Datensätze prüfe, welche schon geöffnet sind, ist das Ergebnis immer das gleiche.

Bei Debug.Print rst.EditMode ist das Ergebnis immer 0. Aber streng genommen editiere ich ja auch nichts wenn ich mir die Datensätze in einem Formulat anzeigen lasse. Ziel soll ja sein, dass wen jemand auf eine bestimmte Gruppe von DS zugreift, um was auch immer zu damit tun, diese für weitere Nutzer Tabu sind.

Nochmals Danke für deine Hilfe.

fraeser
04.05.2011, 15:02
Also meine Access-Hilfe ist da wohl etwas falsch (2007).
Auf jeden Fall gibt es die Werte dbEditAdd (2), dbEditInProgress (1) und dbEditNone (0).
Probier doch mal aus, ob sich die Werte ändern, wenn Du einen Satz bearbeitest.

Forza SGD
04.05.2011, 15:50
hatte ich ja - ich habe über einen anderen Account auf einen DS zugegriffen und geändert. Mit meinem Account habe ich dann geschaut wie der editmode ist - ergebnis war = 0!

Thomas Möller
04.05.2011, 16:10
Hallo!

Ausgangspunkt meinen Problems ist ein Formular, auf welchem den Nutzer den Namen eines Mitarbeiters auswählt - hat er dies getan öffnet sich ein weiteres Formular was alle diesem Mitarbeiter zugeschlüsselten Datensätze anzeigt. Da mehrere User gleichzeitig zugreifen hätte ich gern dass wenn ein weiterer nutzer den gleichen Namen wählt das Formular mit den entsprechenden datensätzen nicht angezeigt wird und mittel Msgbox darauf verwiesen wird, das der Mitarbeiter bereits in bearbeitung ist.

Dann ist doch das After-Update-Ereignis des Steuerelements, bei dem die Mitarbeiterauswahl erfolgt, fast shon der ideale Ort, um den Vorschlag aus #2 umzusetzen.

HTH

Forza SGD
04.05.2011, 16:20
Hallo Thomas,

Diese Lösung hab ich bereits so umgesetzt. Daran soll`s nicht scheitern. Mich würde dennoch interessieren ob ein Lösung wie in #1 möglich wäre. Und wenn ja wie man herausbekommen könnte, ob ein Datensatz derzeit irgendwo anders in der DB in Nutzung ist. Qusi ob er gerade editiert, gelsen, angezeigt etc. wird.

Thomas Möller
04.05.2011, 16:33
Hallo!

Mich würde dennoch interessieren ob ein Lösung wie in #1 möglich wäre. Und wenn ja wie man herausbekommen könnte, ob ein Datensatz derzeit irgendwo anders in der DB in Nutzung ist.

Dann schau doch mal, ob Dich dieser Code hier weiter bringt:
http://www.*************************334251_0_0_asc.php

CU

Forza SGD
04.05.2011, 16:59
Besten dank - ich schaus mir daheim mal an!

ebs17
04.05.2011, 17:34
wie man herausbekommen könnte, ob ein Datensatz derzeit irgendwo anders in der DB in Nutzung ist. Qusi ob er gerade editiert, gelsen, angezeigt etc. wird.
Das in der Gesamtheit wird Dir nicht gelingen. Lesen+Anzeigen kannst Du nur überwachen, wenn Du die Gesamtheit der Frontends überwachst, und das dürfte recht schwierig sein. Das Backend (die Tabelle) liefert dafür keinen Hinweis.

Ob ein Datensatz editiert wird, kann man durch die sich daraus ergebende Sperrung ermitteln. Mögliche Prüfmethode: Du versuchst, bei dem betreffenden Datensatz einen unkritischen Wert mit sich selbst zu überschreiben. Im Falle einer Sperrung erzeugt man einen auswertbaren Fehler.

Daher erscheint mir der Vorschlag von fraeser in #2 als praktikabel, sicher und einfach.

Die theoretisch auch denkbare Variante, die betreffende Tabelle in einer Datei ohne Mehrnutzerfähigkeit oder mit exklusiver Öffnung zu verwenden, dürfte weit weniger praktikabel sein.

Forza SGD
04.05.2011, 17:48
Hallo Ebs,

Gut dann ist das Thema wohl vom Tisch. Ich hatte jetzt auch die Variante mit der Flag umgesetzt. Nun hab ich aber die bedenken was passiert wenn was außerplanmäßiges geschieht - beispielsweise die DB schießt sich ab etc - bleibt der DS dann nicht gesperrt, bzw. ist das nicht recht aufwendig die Eventualitäten abzufangen?

Danke für die Hilfe

achtelpetit
04.05.2011, 17:55
Das ist schon so, wenn ein User sein Frontend abschießt oder sonstwie das flag nicht zurückgesetzt wird, dann bleibt der DS gesperrt.
Eine sichere Methode, dieses Problem zu umgehen, kenne ich nicht. Wahrscheinlich gibt's auch keine, denn vom Zustand des FE erfährt das BE nix. Du könntest statt eines Ja/Nein-flags die Userkennung in die Tabelle schreiben, dann weiß man wenigstens, wer der Übeltäter war.

fraeser
04.05.2011, 17:56
Vielleicht hast Du einen Admin-Bereich im FE. Da kannst Du z.B. per Button alles gesperrten DS wieder entsperren...

ebs17
04.05.2011, 18:05
Im Falle des "Abschießens der DB" ist die nachträgliche Korrektur eines einzelnen Flags sicher eine sehr übersichtliche und beherrschbare Maßnahme, andere dürften aufwändiger sein.

Forza SGD
04.05.2011, 18:24
Hmm - es wird sich schon ne passende Lösung finden - die Idee mit der User ID wird wohl nicht für mich in Frage kommen - da krieg ich ärger mit unserem Betriebsrat. Im Adminbereich etwas bereitzustellen wird wohl das einfachste sein!

Besten Dank für eurer Engagement!

Forza SGD
05.05.2011, 11:38
Also ich hab mich erstmal für die "Flag" Variante entschieden. Anbei habe ich noch einen Beitrag aus einem anderen Forum. Diese Lösung bezieht sich auf die "RecordsLocks" Methode.

Zitat: Bitsqueezer


Hallo,

für diesen Zweck kannst Du (theoretisch) die Eigenschaft "RecordLocks" des Formulars benutzen, die man auf "Edited Record" einstellen kann, so daß (theoretisch) nur der editierte Datensatz gesperrt wird.
Es ist aber eine alte Access-Krankheit, daß hierbei mehr als ein Datensatz gesperrt wird (getesteterweise auch bei Access 2007 noch immer), so daß auch einige andere Datensätze plötzlich nicht mehr bearbeitbar sind.
Es könnte sein, daß diese Funktion besser funktioniert, wenn die Tabelle in einem Access- oder SQL-Server-Backend liegt, das habe ich nicht ausprobiert (nur mit zwei Formularen auf einer lokalen Tabelle). Ich verwende keine pessimistischen Locks, das ist mir zu umständlich.

Ansonsten, so es denn dann auch wirklich nur der editierte Record ist, der gesperrt ist, sieht man im Datensatzmarkierer ziemlich schnell ein Verbotsschild und man kann kein Feld mehr editieren. Wenn man zusätzlich eine Fehlermeldung ausgeben möchte (besser nicht als Messagebox, das könnte sehr stark nerven), kann man zum Beispiel ein gesperrtes Textfeld (hier "txtMessage") auf das Formular setzen und dann den folgenden Code im Form Current Event verwenden:

Private Sub Form_Current()
Dim rs As DAO.Recordset

On Error GoTo Form_Current_Error
Me.txtMessage = ""
DoEvents

If Me.NewRecord Then
Me.txtMessage = "New Record"
Exit Sub
End If
Set rs = CurrentDb.OpenRecordset("SELECT Test FROM Table1 WHERE ID=" & Nz(Me.ctlID, 0), dbOpenDynaset, dbSeeChanges, dbPessimistic)
If Not rs Is Nothing Then
If Not (rs.EOF And rs.BOF) Then
rs.Edit
End If
End If

Form_Current_Exit:
If Not rs Is Nothing Then
rs.Close
Set rs = Nothing
End If
Exit Sub

Form_Current_Error:
Me.txtMessage = Err.Number & " - " & Err.Description
Resume Form_Current_Exit
End Sub


Hierbei wird die Fehlermeldung in das Textfeld kopiert, so daß man beim Blättern durch die Datensätze gleich informiert wird. Es wird versucht, die aktuell angezeigte ID mit einem Recordset, das ebenfalls auf pessimistisch eingestellt ist, zu editieren (ohne es wirklich zu tun), das löst den Fehler aus. Der SELECT-Befehl muß natürlich angepaßt werden.
Das "dbSeeChanges" kann die Änderungen eines anderen Benutzers anzeigen, dazu kann man den Befehl "rs.Move 0" verwenden, der den aktuellen Datensatz neu lädt. Das ist aber nur im Recordset sinnvoll, für das Formular kann man einfach Refresh verwenden.