2008-11-04 5 views
2

У меня есть служба WCF, которая использует DataContext LinqToSql для извлечения некоторой информации из базы данных. Тип возврата операции является IEnumerable <DomainObject>, и у меня есть вспомогательный метод, который преобразует из таблицы происхождения объекта LINQ к контракту данных WCF следующим образом:Предотвращает ли 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 или каким-то образом предотвращение исключения исключений из этого случая? И если да, то почему?

ответ

0

WCF - это странный зверь, который живет немного за пределами обычного IIS; возможно, стандартная отладка становится глючной. Тем не менее, вы можете попробовать enabling debug exceptions и/или реализовать (и настроить) свой собственный 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; } 
1

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

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

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

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

0

Попробуйте положить следующее в 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

1

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

Я не знаю много о WCF, но это не очень похоже на меня.

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

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

Смежные вопросы