Das Notes Forum
Domino 9 und frühere Versionen => ND7: Entwicklung => Thema gestartet von: aks am 03.01.07 - 11:24:42
-
Hi,
ich habe mir eine CD-Datenbank gebastelt.
Nun möchte ich aber dort noch folgendes drin haben:
Field -> Anzahl gesamt CDs:
Field -> CD-Nummer:
Ich dachte ich mach das evtl. über ein Shared Field aber das funzt net so ganz. Ich will quasi beim erstellen eines neuen Eintrages sehen wie viele CD Einträge befinden sich in der DB (Anzahl gesamt CDs) und dann beim Speichern soll als CD-Nummer die Anzahl +1 genommen werden. Natürlich soll dann die Gesamtanzahl auch aktualisiert werden.
Kann mir jemand nen Tip geben wie ich das recht simpel hinbekomme ?
DANKE
Andi
-
Mit einem shared field bist Du hier vollkommen auf dem Holzweg - shared fields sind wiederverwendbare Felddefinitionen (einmal definiert und in vielen Masken ohne Neudefinition einsetzbar).
Weiterhin ist ein Feld "Anzahl CDs" in einem CD-Dokument sehr verwirrend und eigentlich nichtssagend. Eine CD-Nummer lässt sich auch anders vergeben (vorausgesetzt, diese DB wird nur von einem einzigen Benutzer verwendet!). Du brauchst eine Ansicht nach CD-Nummer, absteigend sortiert. Diese kannst Du dann mit @Subset (@dbColumn (....); 1) auslesen und für das neue Dokument inkrementieren - siehe DesignerHelp.
Bernhard
-
Hi, danke für die Antwort. Die DB soll von mehr als einem User editiert werden. Kann man dann Deine Fromel hierzu abändern, oder wo liegt das Problem wenn mehr als ein user darauf zugreifen ?
Das Feld Anzahl gesamt CDs hatte ich nur angedacht, damit ich die CD Nummer irgendwie hochzählen kann und noch weiß was der letzte Stand war.
-
Altes Thema, nur neuer Mantel: NEIN, es gibt keine vernünftige Lösung zur fortlaufenden Nummerierung.
-
Hallo,
hatte mal ein ähnliches Problem. Habe das mit Script im Exiting eines Feldes (Jahr) gelöst. Müsstest du halt ein bissie abändern, z.B. den Code im Postopen der Maske oder so.
Sub Exiting(Source As Field)
'==========================================================
'Beim Verlassen dieses Feldes wird automatisch, das Feld lfdNr gefüllt.
'Hierzu wird in der Ansicht "Ausbildung - Bewerbungen" das eingegebene
'Jahr gesucht, und die Anzahl der vorhanden Dokumente für dieses Jahr
'gezählt. Das Ergebnis wird mit 1 addiert.
'==========================================================
'Allgemein
Dim work As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim s As New notessession
Dim db As NotesDatabase
Dim view As NotesView
Dim doc As NotesDocument
'Vergleich
Dim Jahr As String
'Zähler
Dim i As Long
Dim i2 As Long
'==========================================================
Set uidoc = work.CurrentDocument
'eingegebenes Jahr speichern
Jahr = uidoc.FieldGetText("Jahr")
If Jahr = "" Then
Msgbox "Sie müssen das Ausbildungsjahr eingeben, damit die lfd. Nummer berechnet werden kann!",," "
Exit Sub
End If
'zu durchsuchende View setzen
Set db = s.CurrentDatabase
Set view = db.GetView("Ausbildung - Bewerbungen")
Set doc = view.GetFirstDocument
'Dokumente zählen
For i = 0 To view.AllEntries.Count
If doc Is Nothing Then Exit For
If Right(doc.Jahr(0),4) = Jahr Then i2 = i2 + 1
Set doc = view.GetNextDocument(doc)
Next
'lfd. Nummer setzen
Set doc = uidoc.Document
doc.lfdNr = i2 + 1
End Sub
Gruß
Demian
-
Das funktioniert aber auch nur solange, wie die DB nur von einem einzigen Benutzer verwendet wird.
Ansonsten gilt die Aussage von Klauss
Und was noch dazu kommt, der Benutzer muss das Feld auch wirklich verlassen.
Was machst du, wenn der User speichert und der Cursor steht noch in diesem Feld. Das Exiting - Event eines Feldes wird nicht immer zuverlässig ausgeführt.
Axel
-
Unter Beachtung aller Sicherheitshinweise hätte ich auch noch einen Vorschlag:
Ein Numberingdocument erstellen
Im Querysave-Event auf das Document Zugreifen
Nummer Hochzählen
Nummer Reinschreiben ( in das Numberingdocument und in das aktuelle Zählerfeld )
Numberingdocument speichern
Das sollte einigermassen brauchbar Funktionieren, tut es bei uns zumindest...
-
Und auch hier gilt:
Das funktioniert aber auch nur solange, wie die DB nur von einem einzigen Benutzer verwendet wird.
-
Du kannst auch eine Pseudonummer vergeben bsp -1.
Und nach dem Speichern einen Agenten auf dem Server starten, der alle Dokumente mit -1 durchnummerieren soll (auf basis eines Profildokuments, dass den aktuellen Zähler enthält).
Normalerweise kann niemals ein Agent zweimal gleichzeitig auf dem Server laufen. (Es gibt aber einen Notes.ini Eintrag, der dieses Verhalten verändert!)
Wenn du über mehrere Repliken hinweg arbeitest, muss beachtet werden, dass der Agent nur auf einem Server ausgeführt wird.
Dann bleibt die Laufnummer so lange -1 bis sie auf dem Server der Nummeriert einschlägt. Dort sollte ein periodischer Agent laufen, der den Hochzählagenten startet.
Man kann sich noch mehr aus denken, dann wird es aber immer schwieriger :)
Ggf. gibt es bei diesen Verfahren Replizierkonflikte aber die treten trotz heftiger Nutzung bei uns fast nie auf;)
Gruss
Christian
-
Hallo,
zu Axel:
Das funktioniert aber auch nur solange, wie die DB nur von einem einzigen Benutzer verwendet wird.
Naja gut, wenn 2 Leute gleichzeitig die Maske speichern, würde es mit dem Code zu Problemen kommen, aber sonst doch nicht, oder?
Und was noch dazu kommt, der Benutzer muss das Feld auch wirklich verlassen.
Was machst du, wenn der User speichert und der Cursor steht noch in diesem Feld. Das Exiting - Event eines Feldes wird nicht immer zuverlässig ausgeführt.
Für den Fall frage ich im Querysave der Maske immer ab, ob alle Felder ausgefüllt sind, wenn nicht wird der Speichervorgang mit entsprechendem Hinweis abgebrochen :)
Gruß
Demian
-
zu Axel:
Das funktioniert aber auch nur solange, wie die DB nur von einem einzigen Benutzer verwendet wird.
Naja gut, wenn 2 Leute gleichzeitig die Maske speichern, würde es mit dem Code zu Problemen kommen, aber sonst doch nicht, oder?
Hab ich ja geschrieben. So lange nur ein User zugreift wird es gut gehen.
zu Axel:
Und was noch dazu kommt, der Benutzer muss das Feld auch wirklich verlassen.
Was machst du, wenn der User speichert und der Cursor steht noch in diesem Feld. Das Exiting - Event eines Feldes wird nicht immer zuverlässig ausgeführt.
Für den Fall frage ich im Querysave der Maske immer ab, ob alle Felder ausgefüllt sind, wenn nicht wird der Speichervorgang mit entsprechendem Hinweis abgebrochen :)
Warum machst du denn dann nicht gleich alles im Querysave-Event?
Axel
-
Abgesehen davon macht der Einsatz im Exiting-Event die ganze nochmals unsicherer: User A legt Dokument an, verlässt irgendwann das betreffende Feld, trägt hier und da noch was ein - dann klingelt das Telefon. Währenddessen zieht User die Erstellung eines neuen Dokuments flott durch und speichert. Da davon das Dokument von User A "nichts weiss", haben jetzt beide Doks die gleiche Nummer, wenn User A speichert.
Im geposteten Code finde ich übrigens keine Sperre dafür, dass bei einem Verlassen des Dokuments bei erneuter Editierung nicht auch wieder eine neue Nummer vergeben wird.
Die Diskussion um fortlaufende Nummern, die wir hier schon so oft geführt haben, sollten wir aber nicht erneut aufkochen. Wer nach "fortlaufend" oder "sequentiell" sucht, wird entdecken, dass wirklich schon alles hierzu gesagt wurde.
Bernhard
-
Die Diskussion um fortlaufende Nummern, die wir hier schon so oft geführt haben, sollten wir aber nicht erneut aufkochen. Wer nach "fortlaufend" oder "sequentiell" sucht, wird entdecken, dass wirklich schon alles hierzu gesagt wurde.
Aber anscheinend haben das noch nicht alle kapiert :-P
-
Moin Bernhard,
habe in dem "Jahres-Feld" unter Eingabe aktiviert die Formel "@if(@isnewdoc)".
Werde aber wohl den Vorschlag von Axel umsetzen und alles im Querysave machen. Dann würde es auch bei deinem Beispiel nicht zu Problemen kommen.
Gruß
Demian
-
Danke für die vielen Beiträge. Das Thema fortlaufende Nummer ist ja wohl wirklich etwas schwieriger :-(
-
... alles im Querysave machen. Dann würde es auch bei deinem Beispiel nicht zu Problemen kommen.
Benutze die Forumssuche - so findest Du die anderen Beispiele, die zeigen, warum das eine so unsichere Kiste ist. Wie gesagt - es ist alles schon zigmal erläutert worden.
Bernhard
-
habe den Beitrag nicht eröffnet. HAbe nur geschrieben, wie ich es gelöst habe. Von daher bin ich mit dem Zusatz von Axel völlig zufrieden ;D
-
Von daher bin ich mit dem Zusatz von Axel völlig zufrieden ;D
Na, dann wünsche ich in der Zukunft viel Spass. Auch mit der Forumssuche wirst Du vermutlich folgendes Beispiel nicht finden, weil es spezifisch an den Code gebunden ist, mit dem Du zufrieden bist:
Da Du stur die Dokumente in der Ansicht zählst, bist Du (eher die anderen - Du bist ja zufrieden) unter anderem folgenden Gefahren ausgesetzt:
- Selten: Wegen der Performance-Belastung steigt mit zunehmender Dokumentanzahl das Risiko, dass User A gerade speichert (und Deinen Code ausführt), während User B diesen Prozess erst startet. Wenn dann nicht schnell genug der View-Index wieer aufgebaut ist - bumm.
- Sicher: Irgendwann löscht mal jemand mindestens ein Dokument, welches nicht gerade zufällig das letzte in der Ansicht ist. Da gibt's dann eine doppelte Nummer. Wenn jemand vielleicht sogar mehrere Dokumente löscht ... daran mag ich gar nicht denken ;D
Bernhard
-
Der Azubi, der diese Dokumente erstellt, ist per ACL schon vom Löschen von Doks ausgeschlossen. Und er/sie ist der/die einzige, der diese Doks erstellt.
Die anderen können zwar in der Datenbank Doks löschen, aber für diverse Ansichten, unter anderem auch für diese, sind im Datenbankereignis Querydocumentdelete Blockaden drin.
-
Ich finde mein oben genannter Ansatz mit Server-Agent für die Nummerierung ist doch ein ganz gangbarer Weg... nur nicht sehr trivial...
Kurz nochmal:
Laufende Nummer 0 oder -1 geben und speichern.
Mit RunOnServer einen Agent für die Nummerierung starten.
Ein Agent mit dem selben Namen wird nicht doppelt im Agent-Manager ausgeführt, dass stellt Doppeltnummerierungen sicher.
Mit Clustern ode Replikation muss man natürlich noch paar Dinge mehr beachten....
Gruss
Chris
-
Chris, ich halte den serverbasierenden Agent sogar für den einzig wirklich gangbaren Weg (back to the centralized roots). Run on server tut aber nicht not. es braucht einen "verantwortlichen Server", und dort sollte das Teil entweder scheduled laufen oder triggered: Wenn Dokumente erstellt oder modifiziert wurden. Echtzeit bekommt man sowieso nicht hin.
Das steht aber alles schon hier im Forum in zahlreichen Postings. Ich sehe aber ein, dass es doch irgendwie immer wieder diskutiert werden muss, da man ja doch nicht alle Beiträge hierzu gleich findet.
Der erste Lösungsansatz muss jedenfalls lauten: Wenn man wirklich (!!!) zwingend fortlaufende Nummern benötigt (!!!): Alles bedenken, Forum durchsuchen, vor allem: Notes / Domino wirklich verstehen (jeder, der das nicht tut, sollte dann eben erstmal bis zur Änderung dieses Zustands die Hände heben). Wenn man dann immer noch auf fortlaufenden Nummern besteht: Eigentlich ist dann die Applikation Notes / Domino falsch ausgewählt.
Bernhard
-
In vielen Fällen, in denen ein Pflichtenheft "fortlaufende Nummern" ausweist, sind eigentlich nur "eindeutige Nummern" gemeint - und auch die müssen nicht zwangsläufig reine Zahlen sein.
Für ein weltweit auf vielen Servern eingesetztes Reklamationssystem habe ich z.B. die folgende Nummerngenerierung verwendet:
njahr:=@Year(@Now);
nmonat:=@Month(@Now);
ntag:=((@Date(@Now)-@Date(njahr;1;1))/24/3600)+1;
nStunde:=@Hour(@Now);
nMin:=@Minute(@Now);
TextNr:=@Text(@Modulo(nJahr;10))+@Right("000" + @Text(ntag); 3)+"."+@Right("0000"+@Text(100*nStunde+nMin);4);
n1:=@Name([CN];@UserName);
Initialen := @Left(@RightBack(n1; " "); 2) + @Left(n1; 2);
Die Letzte Ziffer des aktuellen Jahres, die Tageszahl im Jahr, die aktuelle Uhrzeit in Stunden und Minuten, die Initialen des Mitarbeiters. Davor wird noch ein P für eine Produkt- und ein S für eine Servicereklamation gesetzt. Heraus kommt etwas wie
P-7009.1137 TaFa
Der Erkennungs- und Merkwert für die Mitarbeiter ist hoch. Der Kunde kann an der Reklamationsnummer nicht die Zahl der Reklamationen indirekt ablesen (das sollte man bei allzu sprechenden Nummern durchaus auch im Hinterkopf behalten). Die Anwender kennen die Initialen ihrer Kollegen und sehen sofort an der Nummer, wer diese Reklamation angelegt hat. Sie sehen auch sofort an der Nummer das ungefähre Alter dieser Reklamation. Im Normalfall muß man sich nur eine dreistellige Zahl merken (die 7 gilt ja für jede Reklamation aus diesem Jahr - und es gibt nur wenige Tage, an denen mehr als eine Reklamation eingestellt wird). Wenn mehrere Dokumente am gleichen Tag erstellt werden, kann man diese genau voneinander unterscheiden.
Für den konkreten Anwendungsfall sollte man nach solchen Lösungen eher suchen als sich immer wieder auf die eigentlich unlösbare Aufgabe der fortlaufenden Nummernvergabe zu stürzen.
In 14 Jahren Echtbetrieb gab es keinen Fall einer doppelten Nummer.
Gruß
Norbert
-
Wir haben das in einer Datenbank nach dem Prinzip doppelt hält besser gelöst.
Einmal über ein Dokument (kein Profildokument... Caching hat der Teufel gemacht!), in dem die aktuelle Nummer gespeichert ist. Die wird im Querysave ausgelesen und inkrementiert und wieder reingespeichert. Außerdem haben wir noch eine nach der Nummer sortierte Ansicht von der wir das erste Dokument holen und schauen, ob die neue Nummer auch wirklich größer ist als die größte in der Datenbank.
Damit sind wir seit gut 2 Jahren und bis zu 2000 Dokumenten pro Jahr sehr zufrieden.
-
@SD
Ich will die Diskussion über fortlaufende Nummerierung nicht nochmal anstossen, aber nur soviel sei gesagt, auch deine Lösung unterliegt den, schon mehrfach angesprochenen, Risiken.
Axel
-
Es ist erstaunlich und erschreckend, wie beratungsresistent jemand ist, wenn er sich in den Kopf gesetzt hat, eine fortlaufende Nummer mit Notes zu realisieren.
Die folgenden Punkte sind zwingend erforderlich, wenn es denn tatsächlich gelingen soll:
- alle Anwender vergeben neue Nummern in nur einer Replik (in Repliken auf anderen Servern oder in lokalen Repliken können keine neuen Dokumente mit Nummernvergabe erstellt werden)
- du stellst sicher, daß ein Anwender zur gleichen Zeit nur ein Dokument erstellen kann (z.B. durch Erstellung des Dokuments in einer Dialogbox)
- du stellst sicher, daß für die Ersteller von Nummern keine Leserbeschränkungen auf Dokumente mit fortlaufenden Nummern gibt oder du speicherst die letzte vergebene Nummer in einem separaten leserfeldfreien Dokument und stellst sicher, daß dieses Dokument nie einen Replikationskonflikt hat.
Der Vorschlag, eine vorläufige Nummer zu vergeben und die endgültige Nummer von einem Agenten eintragen zu lassen, der nur auf einem Server läuft, berücksichtigt genau diese Punkte.
Ansonsten bewegst du dich für den Satz "Ich erhalte eine eindeutige fortlaufende Nummer" auf der Skala der Treffsicherheit nur zwischen
"Manchmal", "ziemlich oft" und "meistens".
Die zwei-, drei- oder fünffache "Absicherung" führt bestenfalls zu einer Verschiebung hin zu "Meistens", keinesfalls aber zu einem "Immer".
Wenn dir das reicht, reihst du dich in die lange Schlange derer ein, die das schon vor dir probiert haben - und auch gescheitert sind. Aber dann mußt du dich fragen lassen, wofür du diese Nummer eigentlich brauchst.
Gruß
Norbert
-
Naja, in den meisten Fällen ist es ja nicht so, dass jemandem der Herzschrittmacher stehenbleibt, wenn mal eine doppelte Nummer vorkommt.