Access-o-Mania

Datenbanken (Deutsch/German) => MS SQL-Server => Thema gestartet von: Stele4 am April 17, 2025, 12:43:09

Titel: Query Timeout expired
Beitrag von: Stele4 am April 17, 2025, 12:43:09
Hallo!
Auf eine einfache UPDATE-PathThrough-Abfrage in Access meldet der Treiber "... Query TimeOut expired...".

Zur Fehlereingrenzung wurde eine aehnliche Abfrage in SSMS ausgefuehrt:

use MyDb;
UPDATE tblGross
SET Dsc = Dsc + ' solala'
WHERE ID = 1;

Der Server ist lokal und die Tabelle nicht riesig.
Aber die Abfrage kommt nicht zum Abschluss.

Woran kann das liegen?

Gruss

Titel: Re: Query Timeout expired
Beitrag von: PhilS am April 17, 2025, 12:49:51
Zitat von: Stele4 am April 17, 2025, 12:43:09Zur Fehlereingrenzung wurde eine aehnliche Abfrage in SSMS ausgefuehrt:
Und?
Ich vermute, dabei gab es das Problem nicht?

Zitat von: Stele4 am April 17, 2025, 12:43:09Der Server ist lokal und die Tabelle nicht riesig.
Aber die Abfrage kommt nicht zum Abschluss.

Woran kann das liegen?
Wenn du in Access eine große Menge Datensätze anforderst, bleibt die entsprechende Tabelle gesperrt bis die Daten vollständig abgerufen wurden.

Ein Klassiker, der dieses Problem verursachen kann:
Du öffnest in Access in Formular, dass an eine Tabelle gebunden ist. Dabei werden nur die ersten X (genaue Zahl weiß ich gerade nicht) Datensätze abgerufen.
Wenn die Tabelle mehr Datensätze enthält, bleibt sie gesperrt, bis du im Access-Form an das Ende der Datensätze navigierst.
Falls du vorher ein Update auf diese Tabelle ausführst, warte der SQL Server bis die Sperre aufgehoben ist, oder bist der Timeout eintritt.

Titel: Re: Query Timeout expired
Beitrag von: Stele4 am April 17, 2025, 12:57:36
Hallo Phil!
Das war wohl nicht eindeutig.

Die Aktionsabfrage in SSMS kommt nicht zum Schluss.
Hier gibt es wohl keine Zeitbgrenzung.

Eine SELECT-Abfrage wird sehr schnell ausgefuehrt. In Access und SSMS.

Gruss
Titel: Re: Query Timeout expired
Beitrag von: PhilS am April 17, 2025, 13:19:56
Zitat von: Stele4 am April 17, 2025, 12:57:36Die Aktionsabfrage in SSMS kommt nicht zum Schluss.
Wenn zur gleichen Zeit das/die Access-Formular(e) geöffnet sind, die, wie oben beschrieben, das Problem auslösen können, wäre das logisch.
Was passiert, wenn du Access komplett schließt und dann die Abfrage im SQL Server Management Studio ausführst?
Titel: Re: Query Timeout expired
Beitrag von: markusxy am April 17, 2025, 13:56:19
Zitat von: PhilS am April 17, 2025, 12:49:51Wenn die Tabelle mehr Datensätze enthält, bleibt sie gesperrt, bis du im Access-Form an das Ende der Datensätze navigierst.


Die Logik verstehe ich nicht.
Aus Server Sicht werden doch einfach eine bestimmte Anzahl Datensätze abgefragt und das wars.
Was verursacht den Lock?

OT: Persönlich verwende ich beim Server nur ADO, daher kann ich das Problem natürlich nicht haben.



Titel: Re: Query Timeout expired
Beitrag von: Stele4 am April 17, 2025, 14:26:12
Ich bin neu auf dem Feld und wuerde Markus zustimmen.
Doch Phil hat wohl wieder recht:

- Access-DB zu -> Abfrage in SSMS wird abgearbeitet.
- Access-DB auf -> auch ok
- Formular auf -> Problem

Die RecordSource des Formulars wird bei Form_Load per VBA geschrieben (als PathThrough-Abfrage).
OpenRecordset habe ich jetzt mit "Type:=dbOpenSnapshot" erweitert.
Das fuehrt aber nicht zum Erfolg.

Wie kann ich den Lock verhindern, wenn die ID (Autowert) in der Abfrage vorhanden sein muss?

Gruss

Titel: Re: Query Timeout expired
Beitrag von: PhilS am April 17, 2025, 14:51:56
Zitat von: markusxy am April 17, 2025, 13:56:19Die Logik verstehe ich nicht.

Aus Server Sicht werden doch einfach eine bestimmte Anzahl Datensätze abgefragt und das wars.
Was verursacht den Lock?
Das war's erst dann, wenn der Client auch alle Datensätze abgerufen hat.

Client1 sendet: SELECT * FROM EineTAb WHERE XYZ = 'irgendwas';
100 Datensätze entsprechen dem Kriterium. Der Client ruft aber erstmal nur 50 Datensätze ab.
Client2 sendet: UPDATE EineTAb SET XYZ = 'was anderes' WHERE XYZ = 'irgendwas';
Was soll der Server jetzt machen?
Dem Client1 auf Abruf dann die übrigen 50 DS geben, obwohl sie schon nicht mehr dem Kriterium entsprechen?
Gar keine Daten mehr zu der ursprünglichen Abfrage nachliefern, obwohl die UPDATE-Transaktion alle Datensätze betrifft, auch die bereits an den Client gesendeten?
Das wäre beides inkonsistent. Deshalb hält der Server die Sperre auf den vom ersten SELECT betroffenen Datensätzen, bis sie auch abgerufen wurden oder das Recordset des Selects geschlossen wurde.

Das Ganze lässt sich durch das Locking-Verhalten des Servers steuern, aber das kriege ich jetzt ad-hoc nicht belastbar zusammen.


Titel: Re: Query Timeout expired
Beitrag von: PhilS am April 17, 2025, 14:55:05
Zitat von: Stele4 am April 17, 2025, 14:26:12Wie kann ich den Lock verhindern, wenn die ID (Autowert) in der Abfrage vorhanden sein muss?
Komplett verhindern kannst du den Lock nicht so ohne weiteres.
Du kannst aber dafür sorgen, dass Access schnellstmöglich alle Datensätze abruft und damit der Lock nicht mehr nötig ist.
Das geht mit: Recordset.MoveLast
Titel: Re: Query Timeout expired
Beitrag von: Bitsqueezer am April 17, 2025, 18:06:31
Hallo,

sollte aber nur Formulare mit sehr vielen Datensätzen betreffen, da sich das Lazy Loading dann bemerkbar macht - und "MoveLast" bewirkt sofortiges Laden ohne Lazy Loading.

Ich würde aber auch mal in "Daten" im Formular die Einstellung "Datensätze sperren" überprüfen, im Allgemeinen ist es "Keine Sperrung" hier.

Pass-Through-Abfragen sind per Definition read-only, sollten also an sich ohnehin keine Sperrungen verursachen.
Du könntest aber versuchen, den NOLOCK-hint hinzuzufügen:
SELECT *
FROM yourSchema.yourTable (NOLOCK)

Gruß

Christian
Titel: Re: Query Timeout expired
Beitrag von: PhilS am April 17, 2025, 18:26:55
Zitat von: Bitsqueezer am April 17, 2025, 18:06:31sollte aber nur Formulare mit sehr vielen Datensätzen betreffen, [...]
"sehr viele" ist relativ. Ich denke bereits ab ca. 100 Datensätze kann dieser Effekt auftreten.

Zitat von: Bitsqueezer am April 17, 2025, 18:06:31Ich würde aber auch mal in "Daten" im Formular die Einstellung "Datensätze sperren" überprüfen, [...]
Das dürfte bei ODBC-Backends keine Auswirkung haben.

Zitat von: Bitsqueezer am April 17, 2025, 18:06:31Pass-Through-Abfragen sind per Definition read-only, sollten also an sich ohnehin keine Sperrungen verursachen.
Du könntest aber versuchen, den NOLOCK-hint hinzuzufügen:
Die Erläuterungen in #6 erklären implizit auch, warum read-only hier nicht relevant ist und warum NOLOCK i.d.R. keine gute Idee ist.
Titel: Re: Query Timeout expired
Beitrag von: Bitsqueezer am April 17, 2025, 22:14:00
Hallo,

bei 100 Datensätzen gibt es kein Lazy Loading... "MoveLast" bringt dann auch nichts. Denn die sind so schnell geladen, daß es keine Auswirkungen hat.

Da es um eine PT-Abfrage geht, die immer read-only ist, spielt es keine Rolle, wenn die Daten in der Zwischenzeit von z.B. einem anderen User geändert wurden. Die Daten können nicht verändert werden und zeigen daher möglicherweise nicht den aktuellsten Stand an - aber das ist in einer Multi-User-Datenbank auch zu erwarten. Was man mit einem einfachen "F5" beheben kann.

Gruß

Christian

Titel: Re: Query Timeout expired
Beitrag von: Stele4 am April 17, 2025, 23:26:22
Meine Guete! Mir schwindelt.

Ich war davon ausgegangen, dass ein ReadOnly keine Sperre braucht.
Dabei hatte ich das stueckweise Nachladen ausser Acht gelassen.
Mein naechster Ansatz waere, mit Recordset.Open, ~.Clone und ~.Close die Sperre kurz zu halten.
Die Datensatzmanipulation dann wieder per PathThrough-Aktionsabfragen.

Bin gespannt.

Ich wuensche euch Frohe Ostern!
Dank und Gruss!
Titel: Re: Query Timeout expired
Beitrag von: PhilS am April 18, 2025, 11:15:59
Zitat von: Bitsqueezer am April 17, 2025, 22:14:00Denn die sind so schnell geladen, daß es keine Auswirkungen hat.
Bei den 100 Datensätzen mag ich grob falsch liegen. Es sind nur eben nicht so unfassbar viele Daten, die es braucht bis das Problem auftreten kann.
Wie lange es dauert ist sekundär. Der wesentliche Punkt ist ob/wann das vollständige Abrufen der Daten erfolgt.
Wenn du ein Form öffnest, das an eine ausreichend große Datensatzmenge gebunden ist, wird Access die Daten erst dann vollständig abrufen, wenn du ans Ende der Datensatzgruppe scrollst.

Zitat von: Bitsqueezer am April 17, 2025, 22:14:00Da es um eine PT-Abfrage geht, die immer read-only ist, spielt es keine Rolle, [...]
Während die Abfrage ausgeführt wird, muss der Server für einen konsistenten Zustand sorgen.
Titel: Re: Query Timeout expired
Beitrag von: Bitsqueezer am April 18, 2025, 14:07:43
Hallo,

wir reden über eine read-only-Abfrage, die also Daten nur anzeigen kann. Der Zustand durch eine konkurrierende Datenveränderung jeglicher Art ist vollkommen irrelevant. Es ist eine Momentaufnahme und als solche darf sie auch Daten zeigen, die vielleicht bereits während der Abfrage so nicht mehr existieren.

Hier ein wenig zum Selbstlesen:
https://www.sqlshack.com/understanding-impact-clr-strict-security-configuration-setting-sql-server-2017/

Zum Thema MoveLast hatte ich Dir bereits zugestimmt, nur nicht für 100 Datensätze. Keine Ahnung, warum Du das jetzt weiter diskutierst.

Gruß

Christian
Titel: Re: Query Timeout expired
Beitrag von: Stele4 am April 22, 2025, 11:12:20
Hallo!
Die Quelle fuer das Formular wurde per VBA mit PT-Abfrage zugewiesen.
Danach war weder in Access noch in SSMS der Datensatz Nr. 1 schreibbar.
Also wurde versucht, die Datensatzquelle per Kopie zu trennen (s.u.).
Das funktioniert. Auch in Datensatz 8082.

Aber jetzt kann ich nicht mehr filtern!


Private Sub fbRequery()
'Datenquelle importieren und von Quelle trennen
Dim rst As DAO.Recordset

    Set rst = mdlx_Fct.fcSqlRst(sSql:="SELECT * FROM A_TagLst ORDER BY TagNr;")
    With rst
        .MoveLast
        Set Me.Recordset = .Clone
        .Close
    End With
       
    Me.Recalc
    Set rst = Nothing
   
End Sub
Titel: Re: Query Timeout expired
Beitrag von: Bitsqueezer am April 22, 2025, 13:48:41
Hallo,

ich habe gerade mal ein paar Tests gemacht mit Access und SQL Server.
Im Anhang findest Du die Ergebnisse.

AccessUndSQLServer.xls

Es war kein Problem, parallel zum geöffneten Formular einen UPDATE per SSMS durchzuführen.

Treiber für die Verbindung: ODBC 17 for SQL Server.

Ich habe das Formular jeweils per verlinkter Tabelle (also editierbar in Access) und auch als PT-Query (also read-only) verwendet - parallels UPDATE kein Problem. Auch per Access-Formular, kein Problem.

Auch wenn ich Deinen VBA-Code verwende (mit der Abwandlung, CurrentDb.OpenRecordset auf die PT-Abfrage, aber es ging ja um das ".Clone"), kein Problem.

Manko Deiner Version: Du erstellst eine Kopie des Recordsets (das passiert lokal auf Deinem Rechner), dann weist Du diese dem Formular-Recordset zu. Wenn Du jetzt einen Filter setzt im Formular, dann wird dieser auf das Recordset angewendet. Wenn Du den Filter aufheben willst per Navigationsleiste, wird der Filter aber nicht mehr entfernt - das Recordset hat nun keine Verbindung zum Backend mehr, neue Daten können nicht abgefragt werden.
Dabei darf man nicht vergessen, daß das Formular-Recordset-Objekt ein Wrapper ist, der sowohl ADO- als auch DAO-Recordsets annehmen kann. Es ist also kein "normales" Recordset-Objekt.

Die Daten im Anhang sind aus den SQL Server XEvents entnommen, was die neue Version des SQL Profilers darstellt, einfach gesagt. Also Mitschnitt, was passiert im Hintergrund zwischen Access und SQL Server.

Hier kann man sehen, wie Access die verschiedenen Szenarien abhandelt (Datenbank ist die Standard-Chinook-Demodatenbank für SQL Server, Tabelle "Invoice", mit "Id" als PK).

Verlinkt man die Tabelle direkt in Access und nimmt diese als Formularquelle, verwendet Access diese Abfrage auf dem Server:

SELECT "Id" ,"CustomerId" ,"InvoiceDate" ,"BillingAddress" ,"BillingCity" ,"BillingState" ,"BillingCountry" ,"BillingPostalCode" ,"Total"  FROM "dbo"."Invoice"

Es werden also nur die Spalten, die in den Metadaten der verlinkten Tabelle gespeichert werden (lokal in Access) auf der SQL Server Tabelle abgefragt.

Interessant ist, wie Access nun die Filterung durchführt (hier auf "enthält Faria" in "BillingAddress"):
SELECT "dbo_Invoice"."Id" FROM "dbo"."Invoice" "dbo_Invoice" WHERE ("BillingAddress" LIKE '%Faria%' )
Access fragt nicht die Tabelle ab und holt sich dann die nötigen per WHERE. Stattdessen fragt Access nur nach allen Werten der Spalte "Id" (also PK), auf die das WHERE zutrifft.

Danach wird eine Ausführung vorbereitet für eine System-SP:
declare @p1 int
set @p1=7
exec sp_prepexec @p1 output,N'@P1 int',N'SELECT "Id","CustomerId","InvoiceDate","BillingAddress","BillingCity","BillingState","BillingCountry","BillingPostalCode","Total"  FROM "dbo"."Invoice"  WHERE "Id" = @P1',5
select @p1

Und dann geht das Lazy Loading los, was im Anhang ab Zeile 54 für die DAO-Abfrage-Version enthalten ist, aber im Prinzip genauso auch bei Direktverlinkung passiert.

Unterschied ist: Bei Tabellenverlinkung hat man ja keine Sortierung angegeben, daher ist die Sortierung der PK. Entsprechend ist das Lazy Loading einfacher, weil nicht zuerst die Id-Spalte ermittelt werden muß, sondern einfach eine PK-ID, bis zu der gelesen werden soll (Beispiel):

exec sp_execute 1,5
exec sp_execute 1,15
exec sp_execute 1,50
exec sp_execute 1,90
...

Was hier ausgegeben wird, hängt direkt vom Formular ab: In einem Endlosformular werden zunächst die Datensätze gelesen, die man aufgrund der Anzahl Datensätze (Platz im Formular) direkt sehen kann plus ggf. ein paar mehr. Ab dann alle paar Sekunden die nächsten paar.

Scrollt man mit dem Scrollbalken oder springt man an das Ende, ist es wie bei "MoveLast", die Datensätze werden nun sofort angefordert (beim Scrollen aber auch nur soweit, wie man gescrollt hat).

Also so kann man festhalten, daß es auch bei 100 Datensätzen zu Lazy Loading kommt, weil Access das einfach immer so handhabt, egal wieviele Datensätze nach der Anzahl im Formular noch kommen.

Bei Filterung/Sortierung muß Access hier darüber hinaus auch die IDs erst ermitteln und verwendet dann die IDs, um die Gesamtdaten auszugeben:
Im Beispiel im Anhang in der Query unten:

exec sp_execute 7,79,199,213,228,237,251,253,330,364,371
exec sp_execute 7,372,420,421,25,63,86,87,96,223,226
exec sp_execute 7,282,340,110,183,184,214,229,241,360,408
exec sp_execute 7,446,27,30,262,356,403,414,28,45,73
exec sp_execute 7,135,165,269,326,387,33,49,178,250,259

"7" ist dabei das Handle für diese spezielle Abfrage, die mit dem Prepare erstellt wurde. Dahinter die IDs in der Reihenfolge der Sortierung und Menge wie angefordert.

Am Timestamp kann man sehen, wieviel Zeit zwischen jeder Abfrage liegt:

2025-04-22 12:02:26.3063588
2025-04-22 12:02:43.3057814
2025-04-22 12:02:54.8721028
2025-04-22 12:03:09.1540780
2025-04-22 12:03:22.1853937

Beim Scrollen dagegen (also wie bei MoveLast):
2025-04-22 12:04:50.5943679
2025-04-22 12:04:50.6266118
2025-04-22 12:04:50.6269551
2025-04-22 12:04:50.6273435
2025-04-22 12:04:50.6492832
2025-04-22 12:04:50.6496318
2025-04-22 12:04:50.6499214

Wenn man im Formular die Sperrungen auf "Alle Datensätze" einstellt (gebundene verlinkte Tabelle), meckert der ODBC-Treiber und sagt, das sei nicht möglich. Stellt man auf "Bearbeiteten Datensatz", geht es ohne Probleme, ebenso wie "Keine Sperrung".
Dennoch ignoriert Access "Bearbeiteter Datensatz", es wird in beiden Fällen optimistisches Locking verwendet, also paralleler UPDATE in SSMS auch bei begonnenem Datensatz problemlos möglich. Erst beim Speichern sagt Access natürlich, daß der Datensatz von einem anderen User (SSMS) verändert wurde. Also eindeutig optimistisches Locking.
(In beiden Fällen läßt Access hier aber auch nicht "eigenen Datensatz speichern" zu.)

PT-Query:
Interessant ist, daß Access den Inhalt der PT-Query ganz offensichtlich komplett ignoriert. Es analysiert also nicht, was hier abgefragt wird, es gibt nur die Einstellung in der Abfrage, ob Datensätze zurückgegeben werden oder nicht. Daher wird hier die "SELECT *"-Abfrage 1:1 an SQL Server weitergegeben und nicht, wie man es eigentlich machen sollte, eine konkrete Feldliste verwendet.
Im Unterschied zu einer verlinkten Tabelle/Abfrage hat es sicherlich den Vorteil, daß man bei Änderungen im Backend das Frontend bei so einer Abfrage nicht anpassen muß, allerdings auch keine Kontrolle, welche Felder geladen werden und ob die Feldnamen noch übereinstimmen mit dem, was man im Frontend braucht. Sollte man also, wie immer, besser vermeiden.

Aber viel wichtiger: Auch die Art der Filterung verändert sich. Während Access bei verlinkten Tabellen/Abfragen den Aufbau der Tabelle genau kennt und die Filter an SQL Server anpaßt und weitergibt, gibt es keinen solchen Automatismus bei PT-Queries!
Das bedeutet: Wenn ich einen Filter bei Verlinkung einsetze, geschieht die Filterung direkt auf dem SQL Server. Das mag nicht optimal gestaltet sein und eine SP oder UDF mit einem Filter wäre hier vermutlich ein wenig schneller, aber immerhin kommen nur die Datensätze zurück, die ich haben möchte.

Bei der PT-Query dagegen, wenn man hier nicht selbst einen WHERE- bzw. ORDER BY-String einbaut, werden immer alle Datensätze geladen. Verwendet man dann den Formularfilter, werden die Datensätze wiederum erneut komplett geladen und lokal im Recordset gefiltert.

Fazit aus allen Tests ist aber, daß es in keinem der Szenarios zu irgendwelchen Lock-Problemen kam. Datensätze konnten zu jeder Zeit von beiden Seiten (Access und SSMS) bearbeitet und gespeichert werden (natürlich nicht bei den PT-Abfragen, da ja read-only, aber auch kein Locking bei geöffnetem Formular mit PT-Abfrage).
Auch nicht, obwohl und solange Access alle paar Sekunden per Lazy Loading neue Datensätze angefordert hat.

Man kann also festhalten: MoveLast ist nicht notwendig, um Lockingprobleme zu verhindern, es hilft lediglich, das Lazy Loading abzuschalten, um z.B. die Anzahl Datensätze richtig anzuzeigen bzw. direkt zum Ende scrollen zu können (statt "Scrollbarsprüngen", auch und besonders bei Komboboxen/Listboxen, wo man statt "MoveLast" den Effekt durch Abruf von "ListCount" erzeugen kann).
Es erhöht aber auch die Netzwerklast, weil dann immer alle Datensätze heruntergeladen werden - bei jedem User. Lazy Loading dagegen lädt im Beispiel gerade mal 10 Datensätze auf einmal und wartet dann einige Sekunden, was bei Parallelbetrieb deutlich weniger Last erzeugt - und, wie man sieht, keine Datensätze dabei gesperrt werden. Auch nicht bei "Bearbeiteten Datensatz sperren"-Einstellung.

Die Netzwerklast ist gleichermaßen erhöht, wenn man einfach nur "SELECT * FROM Tabelle" verwendet, ohne einzuschränken, welche Datensätze oder welche Sortierung. Filterungen passieren dann nur lokal. Änderung des Filters muß ggf. keine Datensätze erneut abrufen, in meinen Tests jedoch hat Access die PT-Abfrage vor Filteränderung einfach erneut ausgeführt.

Test war A2013 auf lokalem SQL Server 2022 Developer Edition, ODBC 17-Treiber mit System-DSN.

Nach diesen Tests kann man also nur vermuten, daß im verwendeten VBA-Code, dem verwendeten Treiber oder sonstigen parallel laufenden Clients das Problem mit den Locks entsteht.
Ich würde hier also davon absehen, PT-Queries zu verwenden, wenn man deren SQL nicht an die Situation anpaßt. Am empfehlenswertesten ist eine DAO-Abfrage auf eine verlinkte Tabelle oder, wenn es möglich ist, auf eine verlinkte View, die im Code der View ggf. bereits passende Vorfilterung durchführt (bitte keine Sortierung in Views einbauen, die ist nicht garantiert) und darauf dann eine DAO-Query (also lokal).

Im Formular kann man dennoch "Snapshot" einstellen, was die Daten schneller herunterlädt und genau wie bei einer PT-Abfrage das Formular read-only macht. Zusätzlich kann man noch die "Allow..."-Settings des Formulares anpassen, wenn man bestimmte Änderungen generell verbieten will (AllowEdits auf False etwa läßt den Inhalt aller Felder nicht editieren, Snapshot dagegen schon und sagt erst beim Speichern, daß das nicht änderbar ist).

Gruß

Christian


Titel: Re: Query Timeout expired
Beitrag von: Stele4 am April 26, 2025, 23:10:01
Hallo!
Meinen herzlichen Dank fuer das Interesse und den ausserordentlichen Aufwand.
Ich habe bestimmt nicht die Haelfte von eurem Disput verstanden, aber Einiges konnte ich doch mitnehmen und in mein Weltbild einbauen.

Ein Tutor wies mich darauf hin, dass das Recordset der View aufgrund ihrer Komplexitaet nicht schreibbar ist.
Er hat eine Kopie und konnte es mir demonstrieren.
Ich hatte es nicht so eingeschaetzt. Hatte ich das in dem Hin und Her nicht getestet? Wie erklaere ich das im Forum?

Mit dem Wissen wollte ich heute endlich vorankommen. Doch die Tabelle (Teil der View) liess sich nicht schreiben, sobald das Formular geoeffnet wurde.
Wurde das Formular geschlossen, liessen sich Tabelle und View(!) schreiben.

Ich habe in Access ein neues Formular auf Basis der eingebundenen View generieren lassen und geoeffnet.
Die Tabelle in SSMS liess sich schreiben.
Der Vergleich aller Eigenschaften der Formulare brachte keine Differenz.
Dann habe ich die gebundenen Textfelder aus dem Kopfbereich des alten Formulars in den Kopfbereich des neuen Formulars kopiert.
Die Tabelle in SSMS liess sich jetzt nicht mehr schreiben.
Alles noch mal von vorn. Alles gut.
Nun habe ich die gebundenen Textfelder einzeln kopiert und immer wieder getestet, um den Fehler zu finden.
Die Tabelle in SSMS liess sich immer schreiben.

Jetzt habe ich ein identisches Formular, das wie erwartet funktioniert. ...WTF...

Dank und Gruss
Stele
Titel: Re: Query Timeout expired
Beitrag von: Bitsqueezer am April 27, 2025, 00:22:47
Hallo,

wobei Du noch zwischen View und Query unterscheiden mußt (obwohl beides natürlich irgendwie das gleiche ist). "View" sagt man beim SQL Server und "Query" bei Access.
Views können auf dem SQL Server erstellt werden und wie eine Tabelle verlinkt werden. Zusätzlich können Views und Tabellen sowohl lokal wie auch auf dem Server verbunden werden mit einer neuen Abfrage. Das hat alles so seine Fürs und Widers.
Gerade bei Views mußt Du aufpassen: Access erkennt nicht immer beim Einbinden, welches Feld als eindeutiges Feld zu verwenden ist (also als PK, was aber nicht der PK in der View sein muß, sondern nur ein Feld in der View, das eindeutig sein muß). Access fragt dann beim Einbinden nach einem passenden Feld. Kann man auch per Code machen. Aber wenn man das verpaßt, ist die verlinkte View u.U. nicht mehr beschreibbar, auch wenn sie es auf dem Server ist.

Gruß

Christian
Titel: Re: Query Timeout expired
Beitrag von: Stele4 am Mai 06, 2025, 14:27:06
Hallo Bitsqeezer!
Guter Hinweis! Ist auf der ToDo-Liste. Danke!

Kleiner Nachtrag:
Das neue Formular war noch nicht ganz identisch.
Im Endlosformular soll der aktive Datensatz farblich markiert werden.
Es wurde mit einem Textfeld und 'Conditional Formatting' realisiert.
Dem Textfeld wird im Formularereignis 'Form_Current' die [ID] zugewiesen.
Jetzt zittert das Formular bei jedem Zeilenwechsel und eine Aenderung in einem Feld wird nicht mehr uebernommen, sondern fuehrt zu Timeouts. Auch bei folgenden Klicks.

Immerhin ein reproduzierbarer Zusammenhang.
Ich verzichte auf das Feature und blende die Datensatzmarkierer ein.

Gruss
Stele
Titel: Re: Query Timeout expired
Beitrag von: Bitsqueezer am Mai 06, 2025, 14:42:39
Hallo,

was immer Du mit "Zittern" meinst. Aber natürlich bringt jede grafische Spielerei Performance-Verluste vor allem beim Scrollen in Endlosformulare.
Einen Einfluß von CF auf Speicherung der Inhalte sehe ich aber nicht, da gibt es normalerweise keinen Zusammenhang.

Gruß

Christian
Titel: Re: Query Timeout expired
Beitrag von: Stele4 am August 05, 2025, 09:06:30
Guten Morgen!
Was eben noch funktionierte, tut es nun nicht mehr.
Getestet und 'Gut' befunden, scheiterte es gestern.

Aufbau:
Sql Server 15.0.2000 (local) und MS Access 365
Eine View mit Tabelle T1 und verbundenen Detailtabellen dient als Datenquelle (Snapshot) fuer ein Formular.
Ein weiteres ungebundenes Formular dient zur Aufnahme der zu aendernden Daten und Aufruf einer Stored Procedure, um einen Datensatz in T1 zu aendern.

Zur Eingrenzung wurde eine separate Access-DB erstellt und nur T1 und die View angehaengt.
T1 kann nur beschrieben werden, solange die View in Access geschlossen ist.

Das Problem tritt bei anderen Tabellen und ihren (zum Teil komplexeren) Views nicht auf.

Wie kann die Ursache ermittelt werden?
Wie kann das Problem geloest oder umgangen werden?

Gruss
Stele
Titel: Re: Query Timeout expired
Beitrag von: PhilS am August 05, 2025, 10:58:39
Zitat von: Stele4 am August 05, 2025, 09:06:30Zur Eingrenzung wurde eine separate Access-DB erstellt und nur T1 und die View angehaengt.
T1 kann nur beschrieben werden, solange die View in Access geschlossen ist.
Was passiert, wenn du die View in Access öffnest und dann bis zum letzten Datensatz scrollst (Am einfachsten mit dem >| in der Datensatz-Navigation).


Zitat von: Stele4 am August 05, 2025, 09:06:30Wie kann die Ursache ermittelt werden?
Da du ja eigentlich schon ein konkretes Formular als Ursache identifiziert hast, ist vermutlich Trial&Error mit der Recordsource und den evtl. vorhandenen Rowsourcen von Combo- und Listboxen der einfachste/schnellste Weg.

Der "wissenschaftlich", analytische Weg wird hier beschrieben: Determine Which Queries Are Holding Locks (https://learn.microsoft.com/en-us/sql/relational-databases/extended-events/determine-which-queries-are-holding-locks?view=sql-server-ver17)


Zitat von: Stele4 am August 05, 2025, 09:06:30Wie kann das Problem geloest oder umgangen werden?
Entweder die als Problemursache identifizierte(n) Abfrage(n) so ändern, dass sie nur sehr wenige Datensätze liefern, oder nach Öffnen eines Recordsets explizit an das Ende der Datenätze "scrollen" ( Recordset.MoveLast).
Titel: Re: Query Timeout expired
Beitrag von: Stele4 am August 06, 2025, 11:59:39
Hallo Phil,
nochmals Dank!

Eine View auf 1 Tabelle zu reduzieren, scheint mir sinnfrei.
Die Begrenzung der Anzahl der Datensaetze scheidet aus praktischen Gruenden aus.

Das WorkAround mit MoveLast funktioniert augenscheinlich.

Private Sub Form_Load()
    Call fbReq(bReq:=False)                                 'Daten laden (Teil 1 + Rest)   
End Sub

Private Sub fbReq(Optional bReq As Boolean = True)
'Import aller Datensaetze durch 'Scrollen' bis ans Ende
' -> Verhindern LazyLoading und Lock Tabellen in SqlSrv, da alle Daten uebertragen
Dim lngMem As Long

    With Me                                                 'Formular
        lngMem = Me!ID                                          'ID des aktuellen Datensatzes       
        .Painting = False                                       'Bildaktualisierung AUS
        If bReq Then .Requery                                   'Datenquelle neu laden (wenn gefordert)
        .Recordset.MoveLast                                     'Sprung zum letzten Datensatz
        .Recordset.FindFirst "ID = " & lngMem                   'zurueck zum vorigen Datensatz
        .Painting = True                                        'Bildaktualisierung EIN       
    End With

End Sub

Der Code von 'Determine Which Queries Are Holding Locks' hat bei mir leider nicht funktioniert.
Es gibt einige Fehlermeldungen, die ich noch nicht deuten kann. Auch CoPilot kommt da an seine Grenzen.

Gruss und Dank!
Stele