2 Stimmen

Unterdrückt WCF Ausnahmen der ersten Chance?

Ich habe einen WCF-Dienst, der einen LinqToSql DataContext verwendet, um einige Informationen aus einer Datenbank abzurufen. Der Rückgabetyp der Operation ist IEnumerable <DomainObject >, und ich habe eine Helper-Methode, die von der Tabelle abgeleitete LINQ-Objekt zu einem WCF-Datenvertrag wie folgt konvertiert:

[OperationContract]
public IEnumerable<DomainObjectDTO> RetrieveDomainObjects()
{
    var context = CreateDataContext();
    return from domainObject in context.DomainObjects
           select ConvertDomainObject(domainObject);
}

private DomainObjectDTO ConvertDomainObject(DomainObject obj)
{
    // etc...
}

Dieser Code zeigt ein seltsames Verhalten, wenn ich eine ungültige Verbindungszeichenfolge an den DataContext übergebe. Da er nicht in der Lage ist, die richtige Datenbank zu finden, löst der obige Code vermutlich eine SqlException aus, wenn er die IEnumerable aufzählt <DomainObjectDTO > wenn die Serialisierung stattfindet. Wenn ich diesen Code jedoch in meinem Debugger ausführe, sehe ich auf der Serverseite überhaupt keine Ausnahme der ersten Chance! Ich habe den Debugger auf der Registerkarte Ausnahmen angewiesen, bei allen ausgelösten CLR-Ausnahmen abzubrechen, und das tut er einfach nicht. Ich sehe auch nicht die charakteristische "First chance exception"-Meldung im Ausgabefenster.

Auf der Client-Seite erhalte ich eine CommunicationException mit einer Fehlermeldung in der Art von "The socket connection terminated unexpectedly". Keine der inneren Ausnahmen gibt einen Hinweis auf die zugrunde liegende Ursache des Problems.

Der einzige Weg, wie ich das herausfinden konnte, war, den LINQ-Code so umzuschreiben, dass der Abfrageausdruck innerhalb der OperationContract-Methode ausgewertet wird. Übrigens erhalte ich das gleiche Ergebnis, wenn es ein Berechtigungsproblem gibt, oder wenn ich den DataContext in eine using-Anweisung verpacke, also ist dies nicht nur auf SqlExceptions beschränkt.

Abgesehen davon, dass es nicht ratsam ist, den Rückgabetyp zu einem IEnumerable zu machen <T > und nur die Abfrage irgendwo in den Tiefen des Serialisierers aufzählen, ist WCF unterdrücken oder irgendwie verhindern, dass Ausnahmen in diesem Fall ausgelöst werden? Und wenn ja, warum?

1voto

Darren Punkte 931

WCF scheint, zumindest nach meiner Erfahrung, mit Ausnahmen zu zaubern. Ich bin mir nicht sicher, was es mit Ausnahmen macht, aber ich habe festgestellt, dass, wenn das FaultContract-Attribut verwendet wird, um Ausnahmen zu spezifizieren, die der Vertrag auslösen könnte, es zumindest ein bisschen mehr Informationen für den Client gibt, warum der Fehler aufgetreten ist.

Wir würden auch alle Ausnahmen abfangen und wieder werfen sie als FaultExceptions, etwas wie:

try
{
    DoSomething();
}
catch ( Exception ex )
{ 
   throw new FaultException<CustomException>( new CustomException( ex ), ex.Message );
}

Wenn im Verschuldensvertrag eine kundenspezifische Ausnahme festgelegt ist. Dies scheint dem Kunden ein wenig mehr Informationen über die Ausnahme zu geben. Also ich vermute, wenn Sie SQLException als Teil des FaultContract hinzufügen, dann wird es an den Client gesendet werden.

1voto

Tim Lovell-Smith Punkte 14066

unterdrückt oder verhindert WCF irgendwie, dass Ausnahmen in diesem Fall ausgelöst werden? Und wenn ja, warum?

Ich weiß nicht viel über die WCF, aber das klingt für mich nicht sehr wahrscheinlich.

Das Besondere an der First-Chance-Exception ist, dass sie direkt an den Debugger geht und dieser die Möglichkeit hat, sie zu sehen vor die Ausnahme tatsächlich ausgelöst wird - daher der Ausdruck "erste Chance" - hat der Debugger die "erste Chance", die Ausnahme zu behandeln. Wie könnte etwas diese umgehen? Es müsste eine Möglichkeit geben, das Auslösen der Ausnahme komplett zu verhindern. (Gibt es Sicherheits- oder Zuverlässigkeitsfunktionen in der CLR, die dies tun können?).

Die beste alternative Erklärung, die ich vorschlagen kann, ist, dass etwas vor dem Punkt schief geht, an dem Sie erwarten, dass die SqlException ausgelöst wird. Ich würde versuchen, auch auf nicht verwaltete Ausnahmen, nicht nur verwaltete Ausnahmen, für den Fall, dass es ein Fall von z.B. etwas schief geht in nicht verwalteten Serialisierung Code versuchen, die verwaltete IEnumerable oder einige CLR-Bug zu verwenden...

0voto

Timothy Khouri Punkte 30565

Haben Sie Ihre " IncludeExceptionDetailInFaults " Einstellungen? (aus Sicherheitsgründen ist sie standardmäßig auf "false" eingestellt).

0voto

Marc Gravell Punkte 970173

WCF ist ein seltsames Wesen, das etwas außerhalb des normalen IIS lebt; es kann sein, dass das Standard-Debugging Probleme macht. Sie können jedoch versuchen Debug-Ausnahmen aktivieren und/oder die Implementierung (und Konfiguration) Ihrer eigenen IErrorHandler um die Probleme zu protokollieren.

Eine andere Möglichkeit: Gibt es vielleicht einen Iteratorblock ( yield return ) irgendwo in der Mischung hier? Nichts in einem Iterator-Block wird ausgewertet, bis der Enumerator iteriert wird, was zu einigen seltsam anmutenden Problemen mit Daten führen kann, die früher hätten validiert werden müssen. Im obigen Fall ist dies kein Problem (keine yield return ), aber es ist eine, die man beobachten sollte.

Zum Beispiel ist das folgende sehr anders:

var context = CreateDataContext();
var query = from domainObject in context.DomainObjects
       select ConvertDomainObject(domainObject);
foreach(var item in query) { yield return item; }

0voto

kelsmj Punkte 1183

Versuchen Sie, das Folgende in die App.config für Ihren Client und Ihren Dienst einzufügen:

<system.diagnostics>
<sources>
    <source name="System.ServiceModel" switchValue="Verbose,ActivityTracing"
        propagateActivity="true">
        <listeners>
            <add type="System.Diagnostics.DefaultTraceListener" name="Default">
                <filter type="" />
            </add>
            <add name="NewListener">
                <filter type="" />
            </add>
        </listeners>
    </source>
</sources>
<sharedListeners>
    <add initializeData="C:\App_tracelog.svclog"
        type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
        name="NewListener" traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId, Callstack">
        <filter type="" />
    </add>
</sharedListeners>

Laden Sie dann die beiden resultierenden Protokolldateien in den Service Trace Viewer, der mit dem Windows SDK geliefert wird. Auf diese Weise können Sie die tatsächlich ausgelöste Ausnahme sehen.

Links: http://msdn.microsoft.com/en-us/library/aa751795.aspx

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X