DBAPPEND

Advantage Database Server

Moderator: Moderatoren

Antworten
volkrrr
Cut&Paste-Entwickler
Cut&Paste-Entwickler
Beiträge: 43
Registriert: Mo, 20. Feb 2006 16:17

DBAPPEND

Beitrag von volkrrr »

Hallo zusammen,
mir gelingt es nicht, das gleichzeitige Speichern in eine LAGER.DBF sicherzustellen. Klickt man zeitgleich auf speichern, wird nur ein Artikel angelegt, der andere wird in der Regel verworfen.
Hat jemand einen Tipp, was ich da machen kann?
Ich nutze ADS 11.00.0, XBase 1.90.355. Natürlich habe ich den DBAppend() mit NetErr() auf Erfolg abgefragt usw. Hat ja auch 15 Jahr ohne ADS geklappt. Bei der Migration auf ADS treten die Probleme auf.
Benutzeravatar
nightcrawler
1000 working lines a day
1000 working lines a day
Beiträge: 650
Registriert: Di, 24. Apr 2012 16:33
Wohnort: 72184 Weitingen
Hat sich bedankt: 3 Mal
Danksagung erhalten: 96 Mal
Kontaktdaten:

Re: DBAPPEND

Beitrag von nightcrawler »

Was meinst Du mit gleichzeitigem Drücken von "speichern"? In zwei verschiedenen Applikationen? In meiner langen Zeit mit dem ADS ist ein Fehler wie von Dir beschrieben noch nicht vorgekommen, daher vermute ich einen Programmfehler.
Ist denn das Problem mit einem minimalen Programm auch nachvollziehbar?
--
Joachim
Joachim Dürr Softwareengineering
https://www.jd-engineering.de
volkrrr
Cut&Paste-Entwickler
Cut&Paste-Entwickler
Beiträge: 43
Registriert: Mo, 20. Feb 2006 16:17

Re: DBAPPEND

Beitrag von volkrrr »

Ja, Du hast recht. Ich lasse die App auf zwei PCs laufen. Beide geben eine neuen Artikelnummer ein (verschieden) und drücken gleichzeitig auf speichern. Der entscheidende Quelltext lautet:

(cAlias)->(dbappend())
if (cAlias)->(neterr())
confirmbox(,"Artikel konnte nicht angelegt werden!","Achtung",XBPMB_OK,XBPMB_WARNING)
return .F.
else
// Alle Daten schreiben, kann hier eigentlich nur die Artikelnummer sein, ist ja eine Neuanlage
aeval(aEditControls,{ |x| x:getdata() })
endif

cAlias ist das Lager, in aEditControls sind die SLE-Objekte mit den Referenzen auf die Datenbankfelder. Das System läuft in keinen Fehler. Ein Artikel wird angelegt, der andere verworfen.
Der Fehler tritt jedes Mal auf, ist also einwandfrei nachvollziehbar.
Benutzeravatar
Koverhage
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2470
Registriert: Fr, 23. Dez 2005 8:00
Wohnort: Aalen
Hat sich bedankt: 102 Mal
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: DBAPPEND

Beitrag von Koverhage »

Das liegt doch an Dir das die Änderungen verworfen werden.
Du beendest das Speichern nachdem der append nicht geklappt hat.

Besser ist so oder so ähnlich

Code: Alles auswählen

for i := 1 to 10
    lLockStat := cAlias->(dbappend()))
    if lLockStat
       exit
    endif
    sleep(100)
next
IF !lockstat
    // dann Deine Fehlermeldung
else
    // Daten screiben
endif
Gruß
Klaus
volkrrr
Cut&Paste-Entwickler
Cut&Paste-Entwickler
Beiträge: 43
Registriert: Mo, 20. Feb 2006 16:17

Re: DBAPPEND

Beitrag von volkrrr »

Klar, du hast im Prinzip recht, dann müsste aber vorher die Fehlermeldung kommen, die NICHT kommt. Würde sie kommen, wäre alles ok... Das was Du in der FOR - Schleife andeutest habe ich ebenfalls gemacht (nicht abgebildet). Ich habe in dem angegebenen Quelltext den Minimalcode angezeigt, der zum verschwinden des Datensatzes führt. ALSO: Neterr() liefert offensichtlich nicht .F., so dass die confirmbox nicht erscheint, ergo auch das Programm nicht an dieser Stelle mit return .f. terminiert. Das genau ist mein Problem.
Benutzeravatar
nightcrawler
1000 working lines a day
1000 working lines a day
Beiträge: 650
Registriert: Di, 24. Apr 2012 16:33
Wohnort: 72184 Weitingen
Hat sich bedankt: 3 Mal
Danksagung erhalten: 96 Mal
Kontaktdaten:

Re: DBAPPEND

Beitrag von nightcrawler »

kommt überhaupt neterr()? Ausgehend von beiden Code-Beispielen (ich bin kein Xbase..ler) würde ich eher so vorgehen:

Code: Alles auswählen

if ((cAlias)->(dbappend()))
  confirmbox(,"Artikel konnte nicht angelegt werden!","Achtung",XBPMB_OK,XBPMB_WARNING)
  return .F.
else
  // Alle Daten schreiben, kann hier eigentlich nur die Artikelnummer sein, ist ja eine Neuanlage
  aeval(aEditControls,{ |x| x:getdata() })
endif
--
Joachim
Joachim Dürr Softwareengineering
https://www.jd-engineering.de
volkrrr
Cut&Paste-Entwickler
Cut&Paste-Entwickler
Beiträge: 43
Registriert: Mo, 20. Feb 2006 16:17

Re: DBAPPEND

Beitrag von volkrrr »

Ich hätte es eigentlich auch so erwartet. Das Handbuch sagt dbappend() -> nil, also keine Rückgabe. Sons würde ich Dir recht geben. Als BSP-Code findet man im Handbuch:
DbAppend()
IF NetErr()
? "Datensatz konnte nicht erzeugt werden"
ELSE
REPLACE art->ArtNo WITH cArtNo , ;
art->Artikel WITH cArticle
ENDIF

LG
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: DBAPPEND

Beitrag von Tom »

DbAppend() versucht, einen Datensatz anzuhängen und diesen implizit mit RLock() zu sperren. NetErr() reagiert auf diese Sperre - und nicht auf den Versuch, einen leeren Datensatz anzuhängen. Das Anhängen eines Datensatzes kann eigentlich nie scheitern (außer, das Handle für die Tabelle ist ungültig, aber dann bekommt man einen anderen Fehler). Ist für die ADS eigentlich das kompatible oder das ADS-propreitäre Locking aktiviert (letzteres wäre zu empfehlen, wenn man nicht konkurrierend mit ADS und ohne ADS auf die Daten zugreifen will)?

Es müssten also durch beide Stationen mindestens leere Datensätze in der Lagerdatei erzeugt werden. Wenn jedoch nur einer davon mit Daten gefüllt wird, müsste man sich mal die Assign-Codeblöcke der SLEs und den restlichen Code ansehen. Wenn nur ein Datensatz erzeugt wird, ist etwas anderes im Busch.
Herzlich,
Tom
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: DBAPPEND

Beitrag von georg »

Hallo,


ohne Ahnung von ADS zu haben ...

Bei einem SQL-Server würde das auch scheitern, wenn ein Primary Key im Spiel ist.

Beide Stationen legen einen LEEREN Datensatz an, bei dem auch das Schlüsselfeld leer ist. Der Datensatz der ersten Station hat ein leeres Schlüsselfeld, was in diesem Moment zulässig ist. Der (fast) gleichzeitige Versuch der anderen Station, ebenfalls einen Datensatz mit einem leeren Schlüsselfeld anzulegen, scheitert an einer Verletzung des Primary Key: es gibt schon einen Satz mit leeren Schlüsselfeld, daher wird der Datensatz nicht angelegt.

Daher macht die schon angesprochene Schleife Sinn: eine Zehntelsekunde später hat der andere Satz ein von leer verschiedenes Schlüsselfeld, und damit kann wieder ein Datensatz mit leerem Schlüsselfeld angelegt werden.

Da keiner der Standard-Index-Treiber für DBF und Konsorten einen echten Primary Key unterstützt, gibt es das Problem bei deren Verwendung nicht.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
volkrrr
Cut&Paste-Entwickler
Cut&Paste-Entwickler
Beiträge: 43
Registriert: Mo, 20. Feb 2006 16:17

Re: DBAPPEND

Beitrag von volkrrr »

Es ist ADS-propreitäre Locking aktiviert. Definitiv wird nur ein Datensatz erzeugt, der auch eine Artikelnummer erhält. Es ex. kein leerer Datensatz. Ich habe noch DBF mit NTX im Gebrauch. In einem anderen Thread versuche ich gerade die Einstellungen für FoxPro Datenbanken mit CDX und ADS zu erfragen. Das klappt im Moment auch noch nicht. Dann kann ich von NTX ganz Abschied nehmen. Ich vermute, dass es damit zusammen hängt. Ohne ADS klappt nämlich alles ohne Probleme (seid 1999!)...
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: DBAPPEND

Beitrag von georg »

Hallo, Volker -


dbAppend() hängt einen leeren Datensatz an, d.h. alle Felder sind mit ihren Initialwerten belegt. Erst danach kannst Du Felder im Datensatz ändern:
// Alle Daten schreiben, kann hier eigentlich nur die Artikelnummer sein, ist ja eine Neuanlage
aeval(aEditControls,{ |x| x:getdata() })
In solchen Fällen rate ich immer dazu, das Programm im Debugger laufen zu lassen und nach dem dbAppend() anzuhalten - dann kannst Du die Feldwerte mal studieren.


Ein Server, der eine Primary Key Direktive versteht und umsetzt, verhält sich ANDERS als es eine UNIQUE Direktive beim Erstellen einer Index-Datei tut. Darum "funktioniert" das unter Clipper, Xbase++ etc., solange kein SQL-Server im Spiel ist.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Antworten