Neuigkeiten:

Wenn ihr euch für eine gute Antwort bedanken möchtet, im entsprechenden Posting einfach den Knopf "sag Danke" drücken!

Mobiles Hauptmenü

Me.Requery, Application.Echo False usw.

Begonnen von peter4400, Oktober 04, 2024, 14:12:31

⏪ vorheriges - nächstes ⏩

peter4400

Hallo,
ich habe zwei User, die eine gemeinsame Kunden-Warteschlange bearbeiten, und die sollen beide an ihren Rechnern mit einer Access-Datenbank auf eine gemeinsame SQL Server Tabelle zugreifen (so eine Art Warteliste, hatte ich letztens schon mal kurz geschildert im Thread "Gleitendes Formular").

Ich grüble, wie ich es am elegantesten löse, dass die Änderung von User A möglichst sofort bei User B sichtbar wird im Access-Formular. Mit einem Timer-Event im Formular habe ich immer ein Flackern beim Requery, auch wenn ich vorher Application.Echo False einstelle. Würde man sowas nicht besser so lösen, dass man beim Starten des Formulars oder wenn User A selbst eine Änderung vornimmt, einmal die Zeit ausliest, irgendwo als timeLastRequery speichert, und dann das Timer-Event nutzt um alle 5 Sekunden oder so zu checken, ob User B nach diesem Zeitpunkt eine Änderung vorgenommen hat, und nur dann das Me.Requery macht mit dem unvermeidlichen Flackern .... ?
Oder gibts ne Möglichkeit für Me.Requery ohne Flackern?


Knobbi38

Hallo Peter,

mit einem Timer-Event das Netzwerk und den SQL-Server zu belasten, ist eigentlich keine gute Idee. VBA ist anders, als andere Programmiersprachen, nicht multithreading fähig, also ist das eigentlich in Access nicht möglich.

Vielleicht gibt es eine Lösungsmöglichkeit mit SQL Query Notifications und ADO das ExecutionComplete Event auszunutzen, was ich aber noch nie getestet habe.

https://learn.microsoft.com/en-us/sql/relational-databases/native-client/features/working-with-query-notifications?view=sql-server-ver15&redirectedfrom=MSDN 

Gruß
Knobbi38
 

peter4400

Danke für deine Idee, habe jetzt folgende Lösung gefunden, die gut zu funktionieren scheint:
Die aktuelle Wartenummer steht jetzt in einer SQL Server Tabelle, die nur diese eine Zeile hat - aktuelle Wartenummer. Die Anwender checken 1x pro Sekunde mit DLookup, ob der Wert dort noch der lokalen Variable globalLongWartenummer entsprichtet, wenn nicht, wird diese Variable geändert. Der Wert wird einem Bezeichnungsfeld zugewiesen in einem ungebundenen Formular. Das klappt wunderbar ohne jedes Flackern, und braucht noch nicht mal ein me.requery. Kommt ein Kunde, klickt der Anwender einmal aufs Bezeichnungsfeld, damit wird der Wert um 1 erhöht und der neue Wert in die Tabelle auf dem Server geschrieben.
Selbst wenn da jetzt 1x pro Sekunde ein DLookup übers Netz geht, ich glaube nicht, dass das irgendwie relevant viel Traffic ist, Performance ist jedenfalls einwandfrei.

Knobbi38

Hallo Peter,

danke für deine Rückmeldung. Ist zumindest eine brauchbare Lösung ohne grossen Aufwand. Es ist Schade, daß es für Access Clients keine Unterstützung für Alerter- oder Messagingdienste gibt.

Gruß
Knobbi38

Bitsqueezer

Hallo,

zum einen könntest Du die Rate deutlich verringern - ein Update alle 10 Sekunden z.B. wäre sicher immer noch schnell genug.

Zum anderen kannst Du den SQL Server entlasten, indem Du die Information von SQL Server auslagerst. Eine einfache Möglichkeit, die keine zusätzlichen Services und Konfigurationen und Rechtevergaben usw. benötigt, besteht darin, in SQL Server einen Linked Server zu einer Access-Datenbank (nicht Deine) zu erstellen. Diese muß nur auf z.B. einem Fileserver liegen und SQL Server (der Serviceaccount, der für diesen verwendet wird) muß per Windows-Berechtigungen auf diese Datei Lese- und Schreibrechte haben. Zu diesem Zweck muß der Service-Account ein Domänenaccount sein, denn die Systemaccounts, die oft dafür verwendet werden, können nur auf den Windows-Rechner zugreifen, auf dem der SQL Server läuft.

Die Access-Datei kann natürlich auf diesem abgelegt werden, aber die Methode soll ja gerade den Netzwerkzugriff auf den SQL Server verringern.

Der SQL Server schreibt dann z.B. per Tabellentrigger die gewünschten Informationen in die Access-Datenbank in geeigneter Form.

Von den Frontends aus kannst Du dann per Timer die Access-Datenbank abfragen, somit sind die Informationen genauso schnell vorhanden und Du belastest lediglich marginal das Netzwerk für die Abfrage auf die zentrale Access-Datei. Der SQL Server wird dadurch nur genau einmal tätig - wenn sich etwas geändert hat.

Ich habe diese Methode schon mal erfolgreich verwendet, um Systemnachrichten an den Client (alle Clients) schicken zu können, die dort zeitnah aufpoppen sollen als Dialogfenster. So müssen nicht 100 Clients jede Sekunde eine Anfrage an den SQL Server schicken, was schon 100 Anfragen pro Sekunde wären.

Gruß

Christian

peter4400

Hallo Christian,
deine Idee klingt interessant, allerdings frage ich mich, ob eine permanente Verbindung Access-Frontend zu Access-Backend tatsächlich weniger Traffic verursacht als mein

tempLongWartenummer = DLookup("longWartenummer", "tblWartenummer", "ID=1")

auf eine eingebundene SQL Server Tabelle. Das Access-Frontend muss ja auch permanent beim Backend nachfragen, ob sich die Tabelle geändert hat?

Peter

Knobbi38

Hallo Peter,

richtig, aber es geht in dem Beitrag von Christian um die Entlastung des MS-SQL Servers. Der müßte dann die ganzen Anfragen beantworten und bei einem "Linked Server" werden de Änderungen vom Server in eine externe Access-DB geschrieben und der Client liest dann aus dieser Access-DB, nicht mehr direkt vom SQL-Server. So wird der Server von diesen Anfragen entlastet.

Wenn Access-DB und SQL-Server auf dem gleichen Gerät liegen, reduziert sich damit auch die Netzlast ein wenig, da die Änderungen nun nicht mehr von den Access-Clients, sondern vom SQL-Server per Trigger gemacht werden.

Gruß
Knobbi38

peter4400

okay, da mag es entsprechende Szenarien geben, aber davon bin ich mit meiner Datenbank weit entfernt schätze ich.

Bitsqueezer

Hallo,

Ulrich hat es ja schon weitestgehend erklärt.
Noch hinzuzufügen wäre, daß Access Backend eine passive Komponente ist, selbst also gar nichts macht. Wenn das Access-Frontend auf ein Access-Backend zugreift, erledigt alles das jeweilige Frontend.
Wenn ein Access-Frontend auf den SQL Server zugreift, wird der SQL Server dadurch beschäftigt, was ihn u.U. von anderen, wichtigeren Aufgaben abhält.

Für den simplen Zweck einer Push-Nachricht wird der Server nur einmal etwas in die Access-Datei schreiben. Deine jeweiligen Frontends werden dadurch nicht performanter, wenn sie nun stattdessen die Access-Datei abfragen, besonders nicht bei extrem vielen DLookups, aber sicherlich auch nicht schlechter in der Performance, da die Abfrage ja nur ganz simpel ist und kaum Daten über das Netzwerk schickt.

Sinnvollerweise sollte halt, wie gesagt, das Access-Backend nicht auf dem SQL Server liegen, sondern auf einem herkömmlichen Fileserver oder sonstwo im Netz.

Gruß

Christian

markusxy

Mein Ansatz würde aufgrund der bisherigen Schilderung so aussehen:
Es gibt in der Tabelle mit der Warteschlange ein Feld, das speichert wer welchen Fall grade von wem bearbeitet wird.
Eine Prozedur am SQL-Server belegt dann mit Hilfe dieses Feldes die nächste zu bearbeitende Nummer und liefert die Nummer (und andere gewünschte Infos) mittels Recordset oder Output Parameter an den Klienten zurück. Da brauchst du dann weder Timer noch sonstige Hilfs-Konstrukte noch sonstige Dauerfeuer.
Du hast einen zuverlässigen Status in dem Moment wo du ihn brauchst ohne Ressourcen zu verschwenden.

Knobbi38

@markusxy

Zitat von: markusxy am Oktober 08, 2024, 10:34:38Du hast einen zuverlässigen Status in dem Moment wo du ihn brauchst ohne Ressourcen zu verschwenden.

Der aktuelle Status steht dann zwar immer bereit, allein die Clients werden ohne Timer sich nicht von selber aktualisieren.

Gruß Ulrich

markusxy

Zitat von: knobbi38 am Oktober 08, 2024, 13:09:01Der aktuelle Status steht dann zwar immer bereit, allein die Clients werden ohne Timer sich nicht von selber aktualisieren.


Das spielt auch keine Rolle.
Im derzeitigen Ansatz wird zwar in Intervallen nachgesehen ob sich was geändert hat und der daraus ermittelte Wert wird dann hinterlegt.
Das Problem: Man kann sich nicht auf den Wert verlassen, da es ja ein Zeitfenster gibt in dem sich was geändert haben könnte. Also kein verlässlicher Zugang und trotzdem eine händische Aktion und zusätzlich sinnlose Netzlast.

Daher ein Vorschlag mit einer zuverlässigen Vorgehensweise - auch wenn mehrere User 'zeitgleich' zugreifen - und einem Klick der ja in jedem Fall erforderlich ist.


peter4400

Hi, ich verstehe nicht, wie das in deinem Beispiel funktionieren soll, dass der SQL Server von sich aus, ohne irgendein "pull" seitens des Clients, irgendwelche Daten an den Client mit der Access Datenbank liefert.

markusxy

Zitat von: peter4400 am Oktober 09, 2024, 11:17:36dass der SQL Server von sich aus, ohne irgendein "pull" seitens des Clients, irgendwelche Daten an den Client mit der Access Datenbank liefert.

Access muss die Daten immer abholen - das sollte klar sein.

Der SQL-Server könnte zwar per Event Änderungen an den Client schicken, aber da die Entwicklung von Access immer 20 Jahre hinterher hinkt, wird das nicht unterstützt.  ;)

OT: Vielleicht beginnst du mal die zitieren Funktion zu verwenden, damit man weiß worauf sich dein Post bezieht.