Benutzer mit den meisten Antworten
ADODB Zugriff auf SQL 2000 benötigt neuerdings (nach mehreren Jahren) die Curserlocation adUseClient

Frage
-
Hallo,
ich habe mehere VB6 Anwendungen, welche per ADODB auf einen SQL Server 2000 zugreifen. Bisher (die letzten 6 Jahre) liefen die Anwendungen einwandfrei (unter NT4, W2K und XP).
Merkwürdigerweise erhielten 2 Anwendungen plötzlich nur noch leere Recordsets vom Server bzw. konnten keine Updates ausführen. Erst nachdem ich die Cursorlocation explizit auf adUseClient gesetzt habe, funktionierte der Zugriff auf den SQ 2000 Server wieder. Vorher wurde die Cursorlocation überhaupt nicht gesetzt.
Hat irgendjemand eine Idee waran das liegen könnte (Updates, Netzwerk, Firewall, etv.) ?
Vielen Dank und Gruß
Gerhard
- Bearbeitet Gerhard Rausch Dienstag, 6. Juli 2010 22:11 Korrektur
Antworten
-
Hallo Gerhard,
Merkwürdigerweise erhielten 2 Anwendungen plötzlich nur noch leere Recordsets vom Server bzw. konnten keine Updates ausführen. Erst nachdem ich die Cursorlocation explizit auf adUseClient gesetzt habe, funktionierte der Zugriff auf den SQ 2000 Server wieder. Vorher wurde die Cursorlocation überhaupt nicht gesetzt.
Hat irgendjemand eine Idee waran das liegen könnte (Updates, Netzwerk, Firewall, etv.) ?
Ich kann dir den genauen Grund nicht nennen, ich denke aber, es müsste ein Windows oder SQL Server Update gewesen sein. Ich habe diesen Effekt auf 2 Windows 2003 Servern vor ca. 1 oder 1 1/2 Jahren auch festgestellt und da wurde an den Servern absolut nichts außer halt die Updates für Windows und SQL Server jeweils installiert.
Der Effekt könnte durch eine Änderung in den ADO Komponenten kommen, so dass anstelle von adUseClient nun adUseServer als Default verwendet wird oder (was ich für wahrscheinlicher halte) dass das Verhalten bei adUseServer geändert wurde.
Bei mir hat sich das so bemerkbar gemacht, dass SELECT SCOPE_IDENTITY() immer NULL zurück lieferte und über den Profiler konnte man sehen, dass die Statements trotz Verwendung einer einzigen Connection in verschiedenen Verbindungen ausgeführt wurden. (Lief seit ca. 1999 problemlos, nur dann irgendwann letztes Jahr nicht mehr)
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community- Als Antwort markiert Gerhard Rausch Mittwoch, 7. Juli 2010 14:06
-
Hallo Gerald,
die CursorLocation ist im Standard immer adUseServer, das hat sich seit MDAC 1.5 nicht geändert.
Und MDAC / SQL Server 2000 Aktualisierungen beschränken sich seit längerem nur noch auf kritische Fehler:wobei die letzte Aktualisierung wie man sieht schon einige Zeit her ist
(was bei Auslaufprodukten kein Wunder ist).Die Frage wäre: Was führst Du konkret an Anweisungen aus?
Da es eine Rückgabe bei adUseClient gibt, ist ein klassisches Problem
die Rückgabe von leeren Recordsets, die auch durch andere als SELECT-
Anweisungen erfolgen, siehe z. B.: http://support.microsoft.com/kb/197528 (uam.)
Auch die Behandlung von Fehlern hat bei ADO/MDAC immer schon Probleme bereitet:
PRB: Recordset Does Not Open with A Stored Procedure that Returns a High Severity ErrorUnabhängig von Microsoft:
Weitere Probleme könnten Virenscanner bereiten, die sich heute teilweise
tief ins Betriebssytem einnisten.Gruß Elmar
- Als Antwort markiert Gerhard Rausch Mittwoch, 7. Juli 2010 14:06
-
Hallo Elmar,
die CursorLocation ist im Standard immer adUseServer, das hat sich seit MDAC 1.5 nicht geändert.
mind. beim Wechsel zu 2.0 gab es dennoch andere, erhebliche Änderungen, welche damals doch zu ziemlichen Problemen bei vielen Anwendungen geführt haben. Die eigentliche Ursache war zwar der Code (bspw. erstellen von Recordsets mit Set ... = Server.CreateObject( ... ) in Schleifen, welche mehr als ca. 100 mal ausgeführt wurden), vor MDAC 2.0 lief das aber trotzdem prima.
Ob da die CursorLocation irgendwann geändert wurde, weiß ich aber nicht.
Die Frage wäre: Was führst Du konkret an Anweisungen aus?
Da es eine Rückgabe bei adUseClient gibt, ist ein klassisches Problem
die Rückgabe von leeren Recordsets, die auch durch andere als SELECT-
Anweisungen erfolgen, siehe z. B.: http://support.microsoft.com/kb/197528 (uam.)Die Problematik lässt sich bei mir auf 3 verschiedenen Servern nachvollziehen. Anwendungen, die jahrelang ohne Probleme liefen, haben dann letztes Jahr irgendwann angefangen, "rumzuspinnen".
Dim Connection, Recordset, NewId Set Connection = Server.CreateObject( "ADODB.Connection" ) Connection.Open ... Connection.Execute "INSERT INTO ..." Set Recordset = Server.CreateObject( "ADODB.Recordset" ) Recordset.Open "SELECT SCOPE_IDENTITY", Connection, 1, 1 ' oder auch 3, 3 oder was anderes NewId = Recordset.Fields( 0 )
...Ist natürlich nur ein Beispiel, nicht vollständig, ... aber hat jahrelang wunderbar funktioniert, dann irgendwann nicht mehr. SCOPE_IDENTITY() lieferte dann NULL zurück und im Profiler konnte man sehen, dass für jede Abfrage eine einzelne Connection vorhanden war. Mit Angabe von Recordset.CursorLocation = adUseClient war es dann wieder so, wie es sein sollte.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community- Als Antwort markiert Gerhard Rausch Mittwoch, 7. Juli 2010 14:06
-
Hallo Stefan,
bei mir schwindet ADODB so langsam aus dem Gedächtnis
und die zum jeweiligen Fehler passende KB sowieso -
schon bei der Suche für oben habe ich zu viele alte Bekannte gefunden ;-))
Bekanntlich war die Anzahl der Fehler von MDAC vor 2.5 legendär,
was sich erst mit 2.6/2.7 (SQL Server 2000) so langsam beruhigte.Wenn für jede Aktion eine eigene Verbindung aufgemacht wird,
liegt das daran, dass die vorherige noch Ergebnisse zum Verarbeiten hat:
PRB: Implicit Connections Created by the SQL Server OLE DB Provider (SQLOLEDB) Are Not Pooledund adUseClient hat den (hier netten) Nebeneffekt, dass Resultsets verarbeitet werden,
auch wenn man sie selbst nicht erwarten würde.Dein Beispiel funktioniert, wobei ich beim Insert-Execute immer ein adUseNoRecords (= 128/ &H80)
mitgeben würde und gleich das Recordset aus dem Execute verwenden -
weil sonst nur Overhead produziert wird.
(Und eine Lehre aus anderen Problemen ist, die ich nicht mehr aufwärmen möchte):Sub InsertWithScopeIdentity() Dim cnnSQLServer As ADODB.Connection Dim rstIdentity As ADODB.Recordset Set cnnSQLServer = New ADODB.Connection With cnnSQLServer .CursorLocation = adUseServer ' adUseClient .CommandTimeout = 5 .Open "PROVIDER=SQLOLEDB.1;INTEGRATED SECURITY=SSPI;DATA SOURCE=.;INITIAL CATALOG=Northwind" End With cnnSQLServer.Execute "INSERT INTO dbo.Orders (CustomerID) VALUES(N'ALFKI');", Options:=adExecuteNoRecords Set rstIdentity = cnnSQLServer.Execute("SELECT SCOPE_IDENTITY() AS OrderID") Debug.Print rstIdentity(0) rstIdentity.Close cnnSQLServer.Close End Sub
(und auch eine längere Schleife übersteht)
Wobei es wie gesagt unter Access lief - und insofern eher mit dem hier nicht mehr installiertem VB 6 vergleichbar ist -
und nicht unter ASP/IIS.Gruß Elmar
- Als Antwort markiert Gerhard Rausch Mittwoch, 7. Juli 2010 14:06
-
Hallo Elmar,
Wenn für jede Aktion eine eigene Verbindung aufgemacht wird,
liegt das daran, dass die vorherige noch Ergebnisse zum Verarbeiten hat:
PRB: Implicit Connections Created by the SQL Server OLE DB Provider (SQLOLEDB) Are Not Pooledund adUseClient hat den (hier netten) Nebeneffekt, dass Resultsets verarbeitet werden,
auch wenn man sie selbst nicht erwarten würde.Grundsätzlich gebe ich dir natürlich Recht und man hätte das sicherlich auch optimieren können. Aber - und das sehe ich als schwerwiegender an - gab es anscheinend wohl doch eine Änderung im Verhalten solcher Abfragen/Komponenten. Wie bei Gerhard lief das jahrelang ohne Probleme und außer WindowsUpdate gabs da definitiv nichts.
Aber seis drum :) Evtl. hilft unser Geschreibsel Gerhard weiter, er kann sich ja ggfs. nochmal dazu äußern.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community- Als Antwort markiert Gerhard Rausch Mittwoch, 7. Juli 2010 14:06
-
Hallo Gerhard,
wenn man im Enterprise Manager guckt, ist das leider nicht mit dem Verhalten von
ADO/OLEDB vergleichbar. Es fängt schon damit an, dass dort ODBC verwendet wird ;-)Mit leeren Recordsets (Resultsets) sind die Rückgaben von INSERT, UPDATE, DELETE usw.
gemeint, wo man im EM nur sieht: (n) Zeilen betroffen.Wenn ihr Trigger einsetzt, so können die Nebeneffekte von dort herrühren,
wenn dort ein SET NOCOUNT ON fehlt.Gruß Elmar
- Als Antwort markiert Gerhard Rausch Mittwoch, 7. Juli 2010 14:47
Alle Antworten
-
Hallo Gerhard,
Merkwürdigerweise erhielten 2 Anwendungen plötzlich nur noch leere Recordsets vom Server bzw. konnten keine Updates ausführen. Erst nachdem ich die Cursorlocation explizit auf adUseClient gesetzt habe, funktionierte der Zugriff auf den SQ 2000 Server wieder. Vorher wurde die Cursorlocation überhaupt nicht gesetzt.
Hat irgendjemand eine Idee waran das liegen könnte (Updates, Netzwerk, Firewall, etv.) ?
Ich kann dir den genauen Grund nicht nennen, ich denke aber, es müsste ein Windows oder SQL Server Update gewesen sein. Ich habe diesen Effekt auf 2 Windows 2003 Servern vor ca. 1 oder 1 1/2 Jahren auch festgestellt und da wurde an den Servern absolut nichts außer halt die Updates für Windows und SQL Server jeweils installiert.
Der Effekt könnte durch eine Änderung in den ADO Komponenten kommen, so dass anstelle von adUseClient nun adUseServer als Default verwendet wird oder (was ich für wahrscheinlicher halte) dass das Verhalten bei adUseServer geändert wurde.
Bei mir hat sich das so bemerkbar gemacht, dass SELECT SCOPE_IDENTITY() immer NULL zurück lieferte und über den Profiler konnte man sehen, dass die Statements trotz Verwendung einer einzigen Connection in verschiedenen Verbindungen ausgeführt wurden. (Lief seit ca. 1999 problemlos, nur dann irgendwann letztes Jahr nicht mehr)
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community- Als Antwort markiert Gerhard Rausch Mittwoch, 7. Juli 2010 14:06
-
Hallo Gerald,
die CursorLocation ist im Standard immer adUseServer, das hat sich seit MDAC 1.5 nicht geändert.
Und MDAC / SQL Server 2000 Aktualisierungen beschränken sich seit längerem nur noch auf kritische Fehler:wobei die letzte Aktualisierung wie man sieht schon einige Zeit her ist
(was bei Auslaufprodukten kein Wunder ist).Die Frage wäre: Was führst Du konkret an Anweisungen aus?
Da es eine Rückgabe bei adUseClient gibt, ist ein klassisches Problem
die Rückgabe von leeren Recordsets, die auch durch andere als SELECT-
Anweisungen erfolgen, siehe z. B.: http://support.microsoft.com/kb/197528 (uam.)
Auch die Behandlung von Fehlern hat bei ADO/MDAC immer schon Probleme bereitet:
PRB: Recordset Does Not Open with A Stored Procedure that Returns a High Severity ErrorUnabhängig von Microsoft:
Weitere Probleme könnten Virenscanner bereiten, die sich heute teilweise
tief ins Betriebssytem einnisten.Gruß Elmar
- Als Antwort markiert Gerhard Rausch Mittwoch, 7. Juli 2010 14:06
-
Hallo Elmar,
die CursorLocation ist im Standard immer adUseServer, das hat sich seit MDAC 1.5 nicht geändert.
mind. beim Wechsel zu 2.0 gab es dennoch andere, erhebliche Änderungen, welche damals doch zu ziemlichen Problemen bei vielen Anwendungen geführt haben. Die eigentliche Ursache war zwar der Code (bspw. erstellen von Recordsets mit Set ... = Server.CreateObject( ... ) in Schleifen, welche mehr als ca. 100 mal ausgeführt wurden), vor MDAC 2.0 lief das aber trotzdem prima.
Ob da die CursorLocation irgendwann geändert wurde, weiß ich aber nicht.
Die Frage wäre: Was führst Du konkret an Anweisungen aus?
Da es eine Rückgabe bei adUseClient gibt, ist ein klassisches Problem
die Rückgabe von leeren Recordsets, die auch durch andere als SELECT-
Anweisungen erfolgen, siehe z. B.: http://support.microsoft.com/kb/197528 (uam.)Die Problematik lässt sich bei mir auf 3 verschiedenen Servern nachvollziehen. Anwendungen, die jahrelang ohne Probleme liefen, haben dann letztes Jahr irgendwann angefangen, "rumzuspinnen".
Dim Connection, Recordset, NewId Set Connection = Server.CreateObject( "ADODB.Connection" ) Connection.Open ... Connection.Execute "INSERT INTO ..." Set Recordset = Server.CreateObject( "ADODB.Recordset" ) Recordset.Open "SELECT SCOPE_IDENTITY", Connection, 1, 1 ' oder auch 3, 3 oder was anderes NewId = Recordset.Fields( 0 )
...Ist natürlich nur ein Beispiel, nicht vollständig, ... aber hat jahrelang wunderbar funktioniert, dann irgendwann nicht mehr. SCOPE_IDENTITY() lieferte dann NULL zurück und im Profiler konnte man sehen, dass für jede Abfrage eine einzelne Connection vorhanden war. Mit Angabe von Recordset.CursorLocation = adUseClient war es dann wieder so, wie es sein sollte.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community- Als Antwort markiert Gerhard Rausch Mittwoch, 7. Juli 2010 14:06
-
Hallo Stefan,
bei mir schwindet ADODB so langsam aus dem Gedächtnis
und die zum jeweiligen Fehler passende KB sowieso -
schon bei der Suche für oben habe ich zu viele alte Bekannte gefunden ;-))
Bekanntlich war die Anzahl der Fehler von MDAC vor 2.5 legendär,
was sich erst mit 2.6/2.7 (SQL Server 2000) so langsam beruhigte.Wenn für jede Aktion eine eigene Verbindung aufgemacht wird,
liegt das daran, dass die vorherige noch Ergebnisse zum Verarbeiten hat:
PRB: Implicit Connections Created by the SQL Server OLE DB Provider (SQLOLEDB) Are Not Pooledund adUseClient hat den (hier netten) Nebeneffekt, dass Resultsets verarbeitet werden,
auch wenn man sie selbst nicht erwarten würde.Dein Beispiel funktioniert, wobei ich beim Insert-Execute immer ein adUseNoRecords (= 128/ &H80)
mitgeben würde und gleich das Recordset aus dem Execute verwenden -
weil sonst nur Overhead produziert wird.
(Und eine Lehre aus anderen Problemen ist, die ich nicht mehr aufwärmen möchte):Sub InsertWithScopeIdentity() Dim cnnSQLServer As ADODB.Connection Dim rstIdentity As ADODB.Recordset Set cnnSQLServer = New ADODB.Connection With cnnSQLServer .CursorLocation = adUseServer ' adUseClient .CommandTimeout = 5 .Open "PROVIDER=SQLOLEDB.1;INTEGRATED SECURITY=SSPI;DATA SOURCE=.;INITIAL CATALOG=Northwind" End With cnnSQLServer.Execute "INSERT INTO dbo.Orders (CustomerID) VALUES(N'ALFKI');", Options:=adExecuteNoRecords Set rstIdentity = cnnSQLServer.Execute("SELECT SCOPE_IDENTITY() AS OrderID") Debug.Print rstIdentity(0) rstIdentity.Close cnnSQLServer.Close End Sub
(und auch eine längere Schleife übersteht)
Wobei es wie gesagt unter Access lief - und insofern eher mit dem hier nicht mehr installiertem VB 6 vergleichbar ist -
und nicht unter ASP/IIS.Gruß Elmar
- Als Antwort markiert Gerhard Rausch Mittwoch, 7. Juli 2010 14:06
-
Hallo Elmar,
Wenn für jede Aktion eine eigene Verbindung aufgemacht wird,
liegt das daran, dass die vorherige noch Ergebnisse zum Verarbeiten hat:
PRB: Implicit Connections Created by the SQL Server OLE DB Provider (SQLOLEDB) Are Not Pooledund adUseClient hat den (hier netten) Nebeneffekt, dass Resultsets verarbeitet werden,
auch wenn man sie selbst nicht erwarten würde.Grundsätzlich gebe ich dir natürlich Recht und man hätte das sicherlich auch optimieren können. Aber - und das sehe ich als schwerwiegender an - gab es anscheinend wohl doch eine Änderung im Verhalten solcher Abfragen/Komponenten. Wie bei Gerhard lief das jahrelang ohne Probleme und außer WindowsUpdate gabs da definitiv nichts.
Aber seis drum :) Evtl. hilft unser Geschreibsel Gerhard weiter, er kann sich ja ggfs. nochmal dazu äußern.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community- Als Antwort markiert Gerhard Rausch Mittwoch, 7. Juli 2010 14:06
-
Hallo,
danke für die vielen Antoworten :-)
Außer
Set connSQL = New ADODB.Connection
und
connSQL.Open "File Name=sqlConn.udl"
gibt es nichts Besonderes.
Die DB Abfragen liefern auch keine leeren Recordsets zurück - zumindest, wenn man die Abfragen z.B. MSSMS öffnet.
Es ist halt blöd, wenn existierende Anwendungen von heute auf morgen nicht mehr das tun, wsa sie jahrelang getan haben.
Wir haben jetzt die Cursorlocation angepaßt und ein paar neue Views auf der Datenbank angelegt. Clientcursor auf >8 Mio Datensätze frisst doch ein etwas mehr Speicher als ein Serverclient.
Gruß
Gerhard
-
Hallo Gerhard,
wenn man im Enterprise Manager guckt, ist das leider nicht mit dem Verhalten von
ADO/OLEDB vergleichbar. Es fängt schon damit an, dass dort ODBC verwendet wird ;-)Mit leeren Recordsets (Resultsets) sind die Rückgaben von INSERT, UPDATE, DELETE usw.
gemeint, wo man im EM nur sieht: (n) Zeilen betroffen.Wenn ihr Trigger einsetzt, so können die Nebeneffekte von dort herrühren,
wenn dort ein SET NOCOUNT ON fehlt.Gruß Elmar
- Als Antwort markiert Gerhard Rausch Mittwoch, 7. Juli 2010 14:47