Page 1 of 2
Client Server als DBServer Ersatz
Posted: Tue Jul 17, 2018 1:11 pm
by Heinrich
Hallo zusammen
Im Englischen "Suggestions" Bereich habe ich gelesen, dass ein Ersatz für DBServer gewünscht ist.
Leider ist mir die englische Sprache nicht geläufig. So kann ich da nicht mit diskutieren.
Also vor ca. 1 Jahr habe ich begonnen, einen DB-Server Ersatz zu programmieren, welcher von bArrayServer abgeleitet ist. Diese Klasse reagiert genau gleich wie ein normaler DB-Server und kann ohne grosse Anpassung an ein VO Fenster gehängt werden. Als Datenbasis verwendet die Klasse MySQL / Maria DB oder SQLite. Es wäre sicher kein allzugrosser Aufwand Postgrees oder Firebird zu unterstützen.
- MySQLArrayServer.png (86.4 KiB) Viewed 602 times
Vielleicht hat ja jemand Interesse.
Heinrich
Client Server als DBServer Ersatz
Posted: Tue Jul 17, 2018 1:25 pm
by wriedmann
Hallo Heinrich,
das hört sich sehr interessant an und wäre auch etwas, was man sich anschauen könnte/sollte - trifft das, was Karl gemeint hat, recht gut.
Ich habe auch von einem australischen Kollegen gelesen, der einen DataServer auf PostgreSQL-Basis geschrieben hat, nur war ich leider nicht in der Lage, Näheres zu erfahren.
Ich habe vor ca. 13 Jahren was Ähnliches in VO geschrieben. Das arbeitet über das HTTP-Protokoll auf Daten, die auf einem Webserver abgelegt sind und kommt komplett ohne lokale Datenhaltung aus. Auch wenn das mit normalen DataWindows arbeitet, ist es doch kein Drop-In-Ersatz für das DBFCDX-RDD.
Ist Dein Server in Vulcan/X# geschrieben? Nur weil ich die .NET ProviderFactory in Deinem Diagramm sehe...
Wolfgang
Client Server als DBServer Ersatz
Posted: Tue Jul 17, 2018 1:37 pm
by Heinrich
Hallo Wolfgang
Der Server ist in X# mit dem Schalter VO geschrieben.
Verwendet wird zudem noch der bArrayServer von Joachim Bieler (könnte man eventuell ablösen).
Heinrich
Client Server als DBServer Ersatz
Posted: Tue Jul 17, 2018 7:44 pm
by wriedmann
Hallo Heinrich,
das wäre sicher mal Wert angeschaut zu werden.
Danke!
Wolfgang
Client Server als DBServer Ersatz
Posted: Sun Jul 22, 2018 3:38 pm
by Heinrich
Hallo Wolfgang
Beiliegend ein kleines Beispiel, welches einen vom DataServer abgeleiteten DataAdapter enthält.
Damit das Beispiel ohne Fremdprodukte läuft, habe ich die Vererbung vom bArrayServer aufgehoben.
Mit MySQL und MariaDB funktioniert das Beispiel einwandfrei. Bei SQLite habe ich noch etwas Probleme.
Das Beispiel benutzt das in xSharp vorhandene "Standard VO MDI" als Grundlage und ist etwas angepasst worden.
Gruss Heinrich
Client Server als DBServer Ersatz
Posted: Sun Jul 22, 2018 3:50 pm
by wriedmann
Hallo Heinrich,
super, danke! Werde ich ausprobieren - MySQL-Datenbanken habe ich ein paar zur Verfügung.
Wolfgang
P.S. ich habe jetzt mal meine Applikationen drauf abgeklopft, ob ich sie mit einem solchen DBServer zum Laufen bringen würde - und bei den meisten würde das nicht funktionieren. Bei den Pflege-Masken wären zwar keine großen Anpassungen notwendig, aber jede Menge Verarbeitungen und Listen sind effektiv so programmiert, daß die nurmit sequentiellem Datenbank-Zugriff laufen, und andernfalls komplett umzuprogrammieren wären.
Client Server als DBServer Ersatz
Posted: Sun Jul 22, 2018 5:01 pm
by Heinrich
Hallo Wolfgang
Was genau meinst Du mit "sequentiell" ?
Hast Du ein kleines Beispiel?
Gruss Heinrich
Client Server als DBServer Ersatz
Posted: Mon Jul 23, 2018 4:09 am
by wriedmann
Hallo Heinrich,
ganz viele Verarbeitungen in meinen Programmen (und Drucke sowieso) laufen so ab, daß ich einen Order setze, dann die Sätze in einer definierten Reihenfolge hintereinander lese, bis ein bestimmter Wert erreicht ist, und meistens dann pro Satz noch Teilsätze lese.
Das sind aber alles Dinge, die mit SQL auch gehen, bzw. noch viel einfacher zu lösen sind - aber halt eine Umprogrammierung bedingen. Das ist aber sehr viel Code, und diese Zeit habe ich nicht.
Das können bestimmte Listen sein, die Auswahl von Sätzen für die Verrechnung, das Zusammensuchen von Daten für Statistiken oder für Abgleich mit anderen Systemen, aber alle Code, der zum Schreiben bzw. Neuschreiben sehr viel Zeit kosten würde.
Mit MySQL sollte man das auch noch irgendwie hinbekommen, das MySQL über das API ein solches sequentielles Arbeiten erlaubt, aber bei MySQL gefällt mir die Lizenz immer weniger - und vor allem verstehe ich, dass Oracle die Kunden lieber bei seiner eigenen Datenbank hätte als bei MySQL.
lg
Wolfgang
Client Server als DBServer Ersatz
Posted: Mon Jul 23, 2018 6:05 am
by wriedmann
Hallo Heinrich,
danke nochmals für das Beispiel - ich denke, das kann manchen beim Übergang zu SQL sehr weiterhelfen.
Für meine Applikationen schaut das aber schwierig aus, da ich zum einen teilweise sehr große Tabellen habe (viele Felder und viele Sätze), und beim Öffnen keine Angabe der benötigten Sätze und/oder Felder mache.
Um bereits in den Fenstern DBF mit SQL austauschen zu können, müsste ich einen ziemlich intelligenten Caching-Algorithmus haben, der z.B. bei einem Order-Wechsel alle gecachten Datensätze verwirft und komplett neu einliest, aber eben immer nur einen Teil, um Client und Datenbank nicht zu sehr zu belasten.
Leider sind meine Applikationen meist sehr stark auf die Datenhaltung in DBFs samt dem entsprechenden Zugriff optimiert, und das fällt mir bei einer SQL-Migration auf den Kopf.
Ich habe aber bereits seit mehr als 15 Jahren Erfahrung mit verschiedenen SQL-Datenbanken - den Königsweg habe ich aber bisher noch nicht gefunden.
Vielleicht sehe ich das alles auch nur viel zu kompliziert....
Wolfgang
Client Server als DBServer Ersatz
Posted: Mon Jul 23, 2018 8:19 am
by Heinrich
Hallo Wolfgang
Als MySQL Alternative bietet sich MariaDB an. Hier stimmt das Lizenzmodell noch und ist zudem auf jeder Synology bereits vorinstalliert.
Wenn Du bei den Fenstern den bArrayServer verwendest, kannst Du da die Sortierung nach jedem Einlesen neu bestimmen. Es geht sogar dynamisch bei einem Orderwechsel im Fenster und das ohne dass die Daten neu gelesen werden müssten.
Ein Beispiel aus meiner Fensterklasse:
Code: Select all
// Suchbegriff ist erstellt, jetzt die Daten mit Defaultsortierung einlesen und an Fenster hängen
SELF:_oSchuetzen:OrderBy(#nachname, #vorname, #ort)
SELF:_oSchuetzen:Where( cSuchStr )
SELF:_oSchuetzen:Execute()
Falls jetzt die Sortierung geändert werden muss, kann dies mit dem bArrayServer ohne neues Einlesen erfolgen
Code: Select all
SELF:_oSchuetzen:CreateOrder({|Server|RTrim(Server:VEREIN)+" "+Server:NACHNAME})
SELF:_oSchuetzen:SetOrder(1)
Betreffend Anpassung hast Du leider recht. Wenn man von DBF auf SQL wechselt fällt je nach vorliegender Business-Logik mehr oder weniger Anpassungsarbeit an. War bei mir auch so. Da ich jedoch schon vor über 10 Jahren damit begonnen habe alle Auswertungen mit mengenorientierten Abfragen zu erstellten und dafür je Datei eine eigene DbServerklasse geschrieben habe, war in diesem Bereich die Anpassung überschaubar.
Beim Wechsel von VO auf xSharp habe ich auch gleichzeitig den Wechsel von DBF auf SQL vollzogen. Dabei habe ich zuerst die ganze Applikation übernommen um zu sehen wo es Inkompatibilitäten hat. War zum Glück nicht allzu schlimm.
Danach habe ich die Serverklassen auf SQL angepasst ohne grosse Optimierung. Erst nachdem die Auswertungen so liefen wie unter VO habe ich begonnen die SQL Zugriffe zu optimieren.
Beispiel VO:
Code: Select all
METHOD GetSkStandblaetter( cSkNr, cJahr, dDatVon, dDatBis ) CLASS DbResultatBP
Local aRet as Array
Local aSave as Array
aSave := {}
// Umgebung sichern
self:SaveUmgebung( @aSave )
// IndexOrder setzen
self:SetOrder("SkJahr")
// auf erstes mögliches Resultat positionieren, kein Softseek
self:Seek( cSkNr+cJahr, false, false )
// alle Resultate der gewünschten Sektion lesen
aRet := {}
Do While .not. self:EoF .and. self:FIELDGET(#sknr) == cSkNr .and. self:FIELDGET(#jahr) == cJahr
// ist das Resultat innerhalb des gewünschten Zeitraumes?
If (self:FIELDGET(#Stbldrk1) >= dDatVon .and. self:FIELDGET(#Stbldrk1) <= dDatBis ) .or. ;
(self:FIELDGET(#Stbldrk2) >= dDatVon .and. self:FIELDGET(#Stbldrk2) <= dDatBis ) .or. ;
(self:FIELDGET(#Stbldrk3) >= dDatVon .and. self:FIELDGET(#Stbldrk3) <= dDatBis )
// gefundenen oder leeren Datensatz lesen
AAdd( aRet, LeseDatensatz( self ) )
Endif
// nächster Record
self:Skip(1)
enddo
// Umgebung restaurieren
self:RestoreUmgebung( aSave )
Return aRet
Beispiel xSharp und SQL:
Code: Select all
METHOD GetSkStandblaetter( cSkNr AS STRING, cJahr AS STRING, cAnlassId AS STRING, dDatVon AS DATE, dDatBis AS DATE ) AS ARRAY
LOCAL aRet AS ARRAY
//
SELF:cSql := "Select * from " + SELF:cTable + " Where verein_id = '" + cSkNr + "'"
SELF:cSql += " and jahr = '" + cJahr + "' and anlassid = '" + cAnlassId + "'"
SELF:cSql += " and STBLDRK1 >= '" + DToS(dDatVon) + "'"
SELF:cSql += " and STBLDRK1 <= '" + DToS(dDatBis) + "'"
aRet := SELF:GetDaten2Array( SELF:cSQL )
RETURN aRet
Heinrich
Ps:
Bei meinem Beispiel "xSharp_SQL_Beispiel.zip" hat sich ein Fehler eingeschlichen.
Methode "_GetPrimaryFields()", Zeile 177
falsch => AAdd( SELF:_aPrimaryFld, myField["ColumnName"]:ToString() )
richtig => AAdd( SELF:_aPrimaryFld, { myField["ColumnName"]:ToString() }) // Array anhängen