{"id":1470,"date":"2008-09-21T17:25:19","date_gmt":"2008-09-21T15:25:19","guid":{"rendered":"http:\/\/www.glorf.it\/blog\/?p=1470"},"modified":"2008-09-21T12:53:44","modified_gmt":"2008-09-21T10:53:44","slug":"try-catch-mit-nebenwirkungen-auf-cursor","status":"publish","type":"post","link":"http:\/\/www.glorf.it\/blog\/2008\/09\/21\/sql-talk\/sql-server\/try-catch-mit-nebenwirkungen-auf-cursor","title":{"rendered":"Try-Catch mit Nebenwirkungen auf Cursor"},"content":{"rendered":"<p>Seitdem sie mit SQL-Server-2005 eingef&#252;hrt wurde, bin ich ein Fan der neuen Fehlerbehandlung. Deswegen empfahl ich deren Einsatz auch gleich in unseren Richtlinien. Leider mussten wir k&#252;rzlich feststellen, dass sie unerwartete Nebenwirkungen hat. <\/p>\n<p>Wir setzen bei uns ganz gerne Stored-Procedure und Functions ein. Nicht nur wegen der &#8211; in der Regel &#8211; besseren Performance gegen&#252;ber den Alternativen, sondern auch weil man deren Implementierung &#228;ndern kann ohne das Anwendungscoding anpassen zu m&#252;ssen. Jetzt hat ein Kollege in seine Stored-Procedure die alte @@ERROR-Fehlerbehandlung durch die Neue mit TRY-CATCH ersetzt und bekam einen h&#228;sslichen Fehler. Wir konnten das ganz leicht reproduzieren und sind im Gespr&#228;ch mit Microsoft &#252;ber das Verhalten. <\/p>\n<ul>\n<li>Man ben&#246;tigt eine Client-Anwendung, die Daten aus einer Stored-Procedure &#252;ber einen Cursor liest. In unserem Fall war das eine Windows-32-Anwendungen auf Basis MFC\/ODBC, aber das ist fast egal: Mit ADO\/OLEDB passiert das gleiche, weil sich der <em>Server<\/em> komisch verh&#228;lt.<\/li>\n<li>Die Anwendung &#246;ffnet einen Cursor, der auch r&#252;ckw&#228;rts navigieren kann, also z.B. static. (Um das mit ODBC zu reproduzieren, muss man mit Srever-Cursors arbeiten. Man darf hier also nicht die Client-Library verwenden, weil damit die kompletten Daten in einen Cache am Client geladen werden und dann dort navigiert wird. Aber wer holt sich diese Spa&#223;bremse schon freiwillig ins Boot, sie wurde eingef&#252;hrt um ODBC-Treibern ohne Cursor-Unterst&#252;tzung auf die Spr&#252;nge zu helfen. Auf Kosten der Performance&#8230;) <\/li>\n<li>Das ResultSet kommt aus einer Procedure P1, die im einfachsten Fall nur ein einzelnes SELECT enth&#228;lt.<\/li>\n<li>Die Anwendung &#246;ffnet den Cursor, liest ein paar S&#228;tze und springt dann wieder zum ersten Datensatz.<\/li>\n<\/ul>\n<p>Wenn in der Stored-Procedure nun ein TRY-CATCH um das SELECT gemacht wird, dann treten in dem Szenario pl&#246;tzlich ein Fehler auf, weil der R&#252;cksprung auf dem Cursor nicht mehr m&#246;glich ist. Auch parallel ge&#246;ffnete, andere Client-Cursor &#8211; auf der gleichen Connection &#8211; k&#246;nnen nicht mehr parallel gelesen werden.<\/p>\n<p>Das liegt daran, dass der SQL-Server anstelle des Static-Cursors auf der Server-Seite pl&#246;tzlich ein Default-ResultSet (&quot;forward-only\/read-only&quot;, auch als &quot;Firehose&quot;-Cursor&quot; bekannt) verwendet. Und das kann freilich keine R&#252;ckspr&#252;nge. Das Default-ResultSet belegt ja bekanntlich auch die ganze Connection und verhindert das andere Cursor ausgelesen werden bis das Default-ResultSet wieder geschlossen wurde. (MARS hilft bei Verwendung der &quot;alten&quot; Schnittstellen wir MFC &#252;brigens auch nicht wirklich weiter.) Schade, dass das von Microsoft nicht dokumentiert wurde.<\/p>\n<p>Wer denkt, er sei mit seiner .Net-Anwendung aus dem Schneider, den muss ich leider entt&#228;uschen, auch hier werden unter der Haube Cursors verwendet, um die Daten auszulesen. Aber freilich kommt es in der Regel nicht vor, dass auf den Cursors rumnavigiert wird. <\/p>\n<p>Daher werden wir wohl empfehlen m&#252;ssen, dass die neue Fehlerbehandlung genau dann nicht eingesetzt wird, wenn das ResultSet mit einem Cursor ausgelesen wird, auf dem entweder rauf und runter navigiert wird oder parallel auf andere Cursor zugegriffen wird. Leider ist das bei den meisten unserer bestehen Windows-32-Anwendungen so. Erst die neue Programmgeneration geht anders vor&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Seitdem sie mit SQL-Server-2005 eingef&#252;hrt wurde, bin ich ein Fan der neuen Fehlerbehandlung. Deswegen empfahl ich deren Einsatz auch gleich in unseren Richtlinien. Leider mussten wir k&#252;rzlich feststellen, dass sie unerwartete Nebenwirkungen hat. Wir setzen bei uns ganz gerne Stored-Procedure und Functions ein. Nicht nur wegen der &#8211; in der Regel &#8211; besseren Performance gegen&#252;ber [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[16],"tags":[303,305,304],"_links":{"self":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/1470"}],"collection":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/comments?post=1470"}],"version-history":[{"count":1,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/1470\/revisions"}],"predecessor-version":[{"id":1471,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/1470\/revisions\/1471"}],"wp:attachment":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/media?parent=1470"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/categories?post=1470"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/tags?post=1470"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}