WCF подавляет исключения первого шанса? - PullRequest
2 голосов
/ 04 ноября 2008

У меня есть служба WCF, которая использует LinqToSql DataContext для извлечения некоторой информации из базы данных. Тип возврата операции IEnumerable <DomainObject>, и у меня есть вспомогательный метод, который преобразует объект LINQ, полученный из таблицы, в контракт данных WCF, например:

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

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

Этот код демонстрирует странное поведение, если я передаю неверную строку соединения в DataContext. Будучи не в состоянии найти правильную базу данных, предположительно приведенный выше код генерирует исключение SqlException при перечислении IEnumerable <DomainObjectDTO>, когда происходит сериализация. Однако, когда я запускаю этот код в моем отладчике, я не вижу исключений первого шанса на стороне сервера! Я сказал отладчику на вкладке «Исключения» разбить все сгенерированные исключения CLR, а он просто этого не делает. Я также не вижу характерного сообщения «Первое исключение» в окне «Вывод».

На стороне клиента я получаю сообщение CommunicationException с сообщением об ошибке в виде строки «Соединение с сокетом было неожиданно прервано». Ни одно из внутренних исключений не дает никаких указаний на первопричину проблемы.

Единственный способ понять это - переписать код LINQ таким образом, чтобы выражение запроса оценивалось внутри метода OperationContract. Кстати, я получаю тот же результат, если есть проблема с разрешениями или если я обертываю DataContext в операторе using, так что он не просто изолирован от SqlExceptions.

Не принимая во внимание нежелательность создания возвращаемого типа в качестве IEnumerable <T> и только перечисление запроса где-то в глубине сериализатора, подавляет ли WCF или каким-то образом предотвращает появление исключений в этом случае? И если да, то почему?

Ответы [ 5 ]

1 голос
/ 26 января 2011

В этом случае WCF подавляет или каким-то образом предотвращает появление исключений? И если да, то почему?

Я мало что знаю о WCF, но для меня это маловероятно.

Особенность исключений первого шанса заключается в том, что он направляется непосредственно к отладчику, и отладчик получает возможность увидеть его до , когда действительно возникает исключение - отсюда и слова «первый шанс» - Отладчик имеет «первый шанс» обработать исключение. Как можно что-то обойти? Это должно быть каким-то способом остановить возникновение исключения. (Есть ли в CLR функции безопасности или надежности, которые могут это сделать?).

Лучшее альтернативное объяснение, которое я могу предложить, заключается в том, что что-то идет не так, как нужно, до того момента, когда вы ожидаете, что будет сгенерировано исключение SqlException. Я бы также попытался рассмотреть неуправляемые исключения, а не только управляемые исключения, в случае, например, случая что-то идет не так в неуправляемом коде сериализации, пытающемся использовать управляемый IEnumerable, или в какой-то ошибке CLR ...

1 голос
/ 04 ноября 2008

WCF, кажется, по крайней мере, по моему опыту, совершает магию с исключениями. Я действительно не уверен, что это делает с исключениями, но я обнаружил, что если атрибут FaultContract используется для указания исключений, которые может выдать контракт, он по крайней мере даст клиенту немного больше информации о причине ошибки произошло.

Мы также перехватываем любые исключения и перезапускаем их как FaultExceptions, что-то вроде:

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

Если в договоре о неисправности указано специальное исключение. Это, кажется, дает немного больше информации клиенту об исключении. Поэтому я подозреваю, что если вы добавите SQLException как часть FaultContract, он будет отправлен клиенту.

0 голосов
/ 04 ноября 2008

Попробуйте добавить следующее в файл App.config для вашего клиента и службы:

<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>

Затем загрузите оба полученных файла журнала в средство просмотра трассировки служб, которое поставляется вместе с Windows SDK. Вы сможете увидеть действительное исключение, выданное таким образом.

Ссылки: http://msdn.microsoft.com/en-us/library/aa751795.aspx

0 голосов
/ 04 ноября 2008

WCF - любопытный зверь, который немного живет за пределами обычного IIS; может случиться так, что стандартная отладка сбивается с толку. Однако вы можете попробовать включить исключения отладки и / или внедрить (и настроить) свои IErrorHandler для регистрации проблем.

Другой вариант: возможно, где-то в миксе есть блок итератора (yield return)? Ничего в блоке итератора не выполняется до тех пор, пока не будет выполнен итератор, что может привести к некоторым странным проблемам с данными, которые должны были быть проверены ранее. В приведенном выше случае это не проблема (нет yield return), но стоит посмотреть.

Например, следующее очень отличается:

var context = CreateDataContext();
var query = from domainObject in context.DomainObjects
       select ConvertDomainObject(domainObject);
foreach(var item in query) { yield return item; }
0 голосов
/ 04 ноября 2008

Настроили ли вы свои настройки IncludeExceptionDetailInFaults ? (по умолчанию «false» в целях безопасности).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...