2008-11-04 47 views
2

我有一个WCF服务,它使用LinqToSql DataContext从数据库中获取一些信息。该操作的返回类型是IEnumerable的<DomainObject>和I具有从表衍生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。由于无法找到正确的数据库,大概列举了IEnumerable <DomainObjectDTO时>序列化时发生了上面的代码抛出SQLException的。但是,当我在调试器中运行此代码时,我根本没有发现服务器端的第一次例外!我在“例外”选项卡中告诉调试器打破了所有抛出的CLR异常,并且它根本没有。我也没有看到输出窗口中的特征“第一次机会异常”消息。

在客户端,我收到了一个CommunicationException,并且出现了一个错误消息:“套接字连接意外终止”。内部的例外都没有提供任何有关问题根本原因的暗示。

我可以算出这个的唯一途径是重写LINQ代码以这样的方式,该查询表达式的OperationContract的方法的内部进行评价。顺便说一下,如果存在权限问题,或者如果我将DataContext包装在using语句中,我会得到相同的结果,所以这不仅仅与SqlExceptions隔离。

忽略使返回类型为IEnumerable并且只在枚举序列化程序的深处枚举查询的不便之处,是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错误的非托管序列化代码中出现问题...

相关问题