AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken C# SQL MessageId aus einer SQLCLR Funktion
Thema durchsuchen
Ansicht
Themen-Optionen

SQL MessageId aus einer SQLCLR Funktion

Ein Thema von Jelly · begonnen am 15. Jan 2007 · letzter Beitrag vom 16. Jan 2007
Antwort Antwort
Benutzerbild von Jelly
Jelly

Registriert seit: 11. Apr 2003
Ort: Moestroff (Luxemburg)
3.741 Beiträge
 
Delphi 2007 Professional
 
#1

SQL MessageId aus einer SQLCLR Funktion

  Alt 15. Jan 2007, 16:18
Datenbank: MSSQL • Version: 2005
Ich habe hier ein Problem mit den SQL Fehlercodes. Ich erklär erst einmal was ich überhaupt mache:

im SQL Server 2005 nutze ich eine .NET Funktion (SQLCLR). Innerhalb dieser .NET Funktion greife ich auf einen Webservice zu, der mir einen Wert einer bestimmten Berechnung zurückliefert. Diesen Wert soll die .NET Funktion dann an den Aufrufer zurückgeben.

Das klappt auch alles so wie es soll, ne richtig feine Sache. Nur habe ich zur Zeit Probleme mit der Fehlerbehandlung. Tirtt im Webservice ein Fehler auf, so knallts mit in der .NET Funktion (in C# geschrieben), welche mir dann den Fehler an den SQL Server zurückliefert. Der sieht dann in etwa so aus:

Msg 6522, Level 16, State 1, Line 2
A .NET Framework error occurred during execution of user defined routine or aggregate 'ReadInt':
System.Web.Services.Protocols.SoapException: Server was unable to process request. -->
Logical Itemname n12 for Device rbg does not exist in loaded itemslist.
System.Web.Services.Protocols.SoapException:
at System.Web.Services.Protocols.SoapHttpClientProtoc ol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtoc ol.Invoke(String methodName, Object[] parameters)
at TOPCService.ReadInt(String Itemname, String DeviceName)
at Functions.ReadInt(String Itemname, String DeviceName)
.

Aus dieser langen Fehlermeldung hab ich mal die wichtigen Dinge blau markiert. Der Fehlermeldungstext wird aus dem Webservice gesetzt, jedoch habe ich da natürlich keine Möglichkeit, die Msg Id zu setzen. Bei jedem Fehler, der auftritt, schmeisst mir der SQL Server immer nur die Msg 6522 zurück. Aber genau diesen Fehler muss ich auswerten, und zwar so effizient wie nur möglich.

Ich dachte daran, in der .NET Funktion in C# den Fehler im catch Block abzufangen, und dort aufgrund des Fehlertextes "Logical Itemname n12 for Device rbg does not exist in loaded itemslist." diesen auszuwerten und eine benutzerdefinierte Msg Id zurückzuliefern. Somit hätte ich eine bessere Flexibilität bei der Auswertung des Fehlers im SQL Server.

Und genau da häng ich. Die C# Funktion sieht zur Zeit so aus:
Code:
public static String ReadString(String Itemname, String DeviceName)
    {
        String S;
        TOPCService OPC;
        try
        {
            OPC = new TOPCService();
            OPC.Url = RegSettings.UrlWebService();
            S = OPC.ReadString(Itemname, DeviceName);
            OPC.Dispose();
        } catch (Exception e) {
            S = "";
            ArgumentException ec = new ArgumentException("Item not found");
            throw ec;
        }

        return (String)S;
    }
Nur krieg ich mit dem Code natürlich die MsgId nicht geändert. Ich müsste im Catch Block den Fehler analysieren können und eine entsprechende exception auslösen. In T-SQL ginge das mit RAISEERROR MsgId,-1,-1 aber in .NET ?

Ich hoff mein Problem wurde verstanden
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#2

Re: SQL MessageId aus einer SQLCLR Funktion

  Alt 16. Jan 2007, 09:38
Du kannst RaiseError als Command durch den Context abschicken. Du musst allerdings den Fehler, den RaiseError innerhalb der .Net Sproc auslöst abfangen und schlucken.
Dann könnte es funktionieren:
Code:
static void RaiseError(int messageId, int severity, int state)
{
  using (SqlCommand command = new SqlCommand("RaiseError(@messageId, @severity, @state)"))
  {
    command.Parameters.AddWithValue("messageId", messageId);
    command.Parameters.AddWithValue("severity", severity);
    command.Parameters.AddWithValue("state", state);
   
    try
    {
      SqlContext.Pipe.ExecuteAndSend(command);
    }
    catch {/*nüschts*/}
  }
}

static void RaiseError(string messageText, int severity, int state)
{
  using (SqlCommand command = new SqlCommand("RaiseError(@messageText, @severity, @state)"))
  {
    command.Parameters.AddWithValue("messageText", messageText);
    command.Parameters.AddWithValue("severity", severity);
    command.Parameters.AddWithValue("state", state);

    try
    {
      SqlContext.Pipe.ExecuteAndSend(command);
    }
    catch {/*nüschts*/}
  }
}
Keine Ahnung, ob das so stimmt. TSQL und das Fehlen von Exceptions darin sind so abartig...
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  Mit Zitat antworten Zitat
Benutzerbild von Jelly
Jelly

Registriert seit: 11. Apr 2003
Ort: Moestroff (Luxemburg)
3.741 Beiträge
 
Delphi 2007 Professional
 
#3

Re: SQL MessageId aus einer SQLCLR Funktion

  Alt 16. Jan 2007, 10:02
Zitat von Elvis:
Keine Ahnung, ob das so stimmt. TSQL und das Fehlen von Exceptions darin sind so abartig...
Danke für deine Mühe. Die Sache hat allerdings 2 Haken:
1. In einer SQLCLR Funktion kann ich nichts über die Pipe senden, weil das in Funktionen leider und unverständlicherweise nicht erlaubt ist
2. Die Fehler sind nach meinem Wissen kummulativ. Durch den Raiseerror würde ich dann wohl höchstens einen weiteren Fehler übergeben. Aber damit könnte ich zur Not noch leben, denn die Variabel @@ERROR enthält ja wohl die zuletzt geworfene Exception.
  Mit Zitat antworten Zitat
Benutzerbild von Jelly
Jelly

Registriert seit: 11. Apr 2003
Ort: Moestroff (Luxemburg)
3.741 Beiträge
 
Delphi 2007 Professional
 
#4

Re: SQL MessageId aus einer SQLCLR Funktion

  Alt 16. Jan 2007, 10:17
OK, das mit dem RAISERROR innerhalb einer Funktion (egal ob .NET oder T-SQL) ist auch unterbunden. Die Fehlermeldung vom SQL Server lautet:
Code:
Msg 6522, Level 16, State 1, Line 4
Invalid use of side-effecting or time-dependent operator in 'RAISERROR' within a function.

Das kann doch nicht sein, dass ich aus einer Funktion heraus dem Aufrufer keinen Fehler übermitteln kann.
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#5

Re: SQL MessageId aus einer SQLCLR Funktion

  Alt 16. Jan 2007, 10:31
Hab' mich gerade mal schlau gemacht. Anscheinend gibt es keine hübsche Lösung dafür.
Das Errorhandling von TSQL ist einfach zu schrottig. Wie wär's mit einem Output parameter, der den Error code angibt?
Dann kannst du die CLR SProc in eine TSQL SProc verpacken, in der kannst du dann RaiseError ausführen. (An deiner Stelle wäre ich spätestens ab diesem Absatz fuchsteufelswild.... )
Tja, was bringt einem CLR Integration wenn das DBMS noch genauso dämlich ist wie 2000?
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  Mit Zitat antworten Zitat
Benutzerbild von Jelly
Jelly

Registriert seit: 11. Apr 2003
Ort: Moestroff (Luxemburg)
3.741 Beiträge
 
Delphi 2007 Professional
 
#6

Re: SQL MessageId aus einer SQLCLR Funktion

  Alt 16. Jan 2007, 13:35
Zitat von Elvis:
Hab' mich gerade mal schlau gemacht. Anscheinend gibt es keine hübsche Lösung dafür.
Ich zwischenzeitlich auch, und das scheint alles nicht so toll zu sein.

Zitat von Elvis:
Das Errorhandling von TSQL ist einfach zu schrottig.
naja, immerhin kann man jetzt wenigstens gegenüber der 2000er Version die Fehler in einem Try...catch Block abfangen.

Zitat von Elvis:
Wie wär's mit einem Output parameter, der den Error code angibt?
Das Problem ist, dass einiges als Funktion deklariert sein muss, da die Funktion weiter in Select-Abfragen genutzt werden soll. Es hilft mir leider nicht weiter eine T-SQL funktion zu deklarieren, die intern ein Stored Procedure aufruft, denn dann hab ich wieder die gleichen Probleme mit dem Raise Error weil der .NET Aufruff im Kontext der T-SQL Funktion aufgerufen wird.

Aber dein obiger Ansatz funktioniert... Für Stored Procedures. Neben lesenden (über Funktion) Zugriff auf Funktionen gibts auch schreibende Stored Procedures, die mit dem gleichem Webservice kommunizieren. Da krieg ich die Fehler abgefangen und kann sie an den Aufrufer mittels raiserror dort auch genau so anzeigen und auswerten.

Zitat von Elvis:
Tja, was bringt einem CLR Integration wenn das DBMS noch genauso dämlich ist wie 2000?
Das DBMS an sich wird dadurch nicht schlecht. Die .NET Integration ermöglicht uns hier zumindest Dinge, die unter 2000 ganz einfach nicht möglich waren.
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#7

Re: SQL MessageId aus einer SQLCLR Funktion

  Alt 16. Jan 2007, 13:41
Zitat von Jelly:
naja, immerhin kann man jetzt wenigstens gegenüber der 2000er Version die Fehler in einem Try...catch Block abfangen.
lol! Naja, wenn man mit MSSQL leben muss mag es einige (fast) sinnvolle Neuerungen im 2005'er geben.
Ich konnte zum Glück jemanden finden, der mir den MSSQL-Krempel freiwillig abgenommen hat.
Nach 3 Monaten war ich reif für die Klapse...
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:10 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz