System.ServiceModel.ExceptionDetail

  今天讨论点技术的问题。System.ServiceModel.ExceptionDetail这个是什么东东?

  我现在正在做的项目,准备用WCF。因为正在设计异常处理部分的解决方案,自然就涉及到了服务器端发生错误,如何传递到客户端的问题。原以为,服务器端的异常通过代理会原样返回,结果发现不是。所有的服务器端错误都会被封装,序列化以后再传回客户端,客户端接收到的始终是System.ServiceModel命名空间下的异常,只有异常的Message属性和原来的异常是一致的。 不过,通过.net的监视工具可以看到这个异常对象包含一个detail属性,是ExceptionDetail类型,通过这个属性可以了解到在服务器端发生的原来的异常的种类等信息。不过,在代码里面却无论如何都找不到这个detail属性,也就是说根本无法了解到服务器发生的异常种类。如何得到ExceptionDetail呢?百思不得其解,到网上查找资料也没什么收获,郁闷······

  最后想到对象浏览器,发现对象浏览器里面System.ServiceModel命名空间下,除了FaultException类和ExceptionDetail类以外还有一个FaultException(Of TDetail)类。类名称里面还包含括号,这可是我第一次看到,也许是少见多怪吧(原来是范型,和C#的表示方法大相径庭),莫非?

  于是最后的代码改成Catch ex As System.ServiceModel.FaultException(Of System.ServiceModel.ExceptionDetail), ok ex.Detail出现了。

  在百度搜索System.ServiceModel.ExceptionDetail的结果是0件,也许是太简单了吧。Google里面找到这样的英文解释(地址: http://msdn2.microsoft.com/en-us/library/system.servicemodel.exceptiondetail.aspx )。

The ExceptionDetail class is the type parameter used as the fault detail object when a

To send a ExceptionDetail object the type must be serializable. For more information on serialization options, see

Specifying Data Transfer in Service Contracts.

  总结一下学到的知识。
  WCF服务器端发生的FaultException异常,如果想要了解其详细内容的话。首先服务器端的服务要进行如下设置,ServiceBehaviorAttribute.IncludeExceptionDetailInFaults 属性或者ServiceDebugBehavior.IncludeExceptionDetailInFaults属性要设置为True。
然后在客户端可以通过捕捉System.ServiceModel.FaultException(Of System.ServiceModel.ExceptionDetail)类型的异常对象,利用其detail属性了解到服务器端异常的具体信息。
 
  下次再有人搜索System.ServiceModel.ExceptionDetail关键字,或许上面的文字会有些帮助。
 
 
System.ServiceModel.FaultException is sent by a service as a result of setting the ServiceBehaviorAttribute.IncludeExceptionDetailInFaults or the ServiceDebugBehavior.IncludeExceptionDetailInFaults property to true.
<think> 我们面对的是两个异常:`System.Reflection.TargetInvocationException` 和 `System.ServiceModel.FaultException<ExceptionDetail>`,并且错误代码是ORA-00933。此外,环境涉及`ObservableCollection<DBParameter>`。 首先,让我们分解问题: 1. **System.Reflection.TargetInvocationException**:这个异常通常表示在反射调用方法时发生了异常,它包裹了实际发生的异常。我们需要查看它的内部异常(InnerException)来了解根本原因。 2. **System.ServiceModel.FaultException<ExceptionDetail>**:这是WCF服务中常见的异常,表示服务端抛出了一个未被处理的异常,并且这个异常被转换成了SOAP错误(Fault)传递到客户端。同样,我们需要查看具体的错误信息。 3. **ORA-00933**:这是Oracle数据库错误,表示SQL命令没有正确结束。常见的可能原因包括: - SQL语句的语法错误。 - 在错误的位置使用了ORDER BY子句(例如,在子查询中使用ORDER BY而外层没有正确结束)。 - 使用了Oracle不支持的SQL语法。 4. **环境**:使用`ObservableCollection<DBParameter>`。这通常用于数据绑定,但在这里可能表示在传递数据库参数时使用了这个集合。 根据引用[1]中提到的解决`TargetInvocationException`的方法(修改注册表),这可能是特定于环境的问题(如加密策略)。但是,引用[1]的上下文是解决UE项目的问题,而我们的问题发生在WCF服务和数据库操作中,因此不一定适用。不过,我们可以将注册表修改作为备选方案。 引用[2]提到了`TargetInvocationException`,但没有具体解决方案。 因此,我们应首先关注ORA-00933错误,因为数据库错误往往是根本原因。然后,再考虑其他异常。 **解决步骤:** **1. 分析ORA-00933错误:** - 检查执行的SQL语句。这个错误通常意味着SQL语法问题。例如: - 在SQL语句中,可能错误地使用了ORDER BY子句,而Oracle要求ORDER BY必须放在整个语句的最后,且子查询中通常不允许使用ORDER BY(除非有TOP-N需求且使用ROWNUM等)。 - 检查SQL语句是否缺少关键字,比如在JOIN操作中缺少ON条件。 - 检查是否使用了Oracle不支持的语法,比如在DELETE或UPDATE语句中使用了JOIN(Oracle中应该用其他方式实现多表更新/删除)。 - 由于异常发生在使用`ObservableCollection<DBParameter>`的环境中,可能是构建SQL语句时参数化查询的拼接出了问题。 **2. 检查代码中的SQL构建:** - 查看生成SQL语句的代码部分,特别是使用`DBParameter`集合的地方。确保参数化查询的拼接正确。 - 注意:在Oracle中,参数占位符使用冒号前缀(例如`:paramName`),而不是SQL Server中的`@paramName`。确保参数化查询的格式正确。 **3. 查看内部异常:** - 由于`TargetInvocationException`和`FaultException`都是包装异常,我们需要捕获并记录它们的内部异常。在调试时,查看`InnerException`属性,以获取更具体的错误信息。 **4. 日志记录:** - 确保服务器端和客户端都有详细的日志记录,特别是记录服务操作执行时抛出的完整异常信息(包括内部异常)。 **5. 注册表修改(备选):** - 如果上述步骤不能解决问题,并且怀疑与加密策略有关(如引用[1]所述),可以尝试修改注册表: - 定位到:`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\FipsAlgorithmPolicy\Enabled` - 将其值设置为0(禁用FIPS算法策略)。 - 注意:修改注册表需要管理员权限,并且修改后需要重启计算机。 **6. 其他可能原因:** - 数据库连接问题:检查数据库连接字符串和网络连接。 - 权限问题:确保数据库用户有执行相应SQL语句的权限。 **具体到代码:** 由于问题涉及`ObservableCollection<DBParameter>`,我们需要检查构建SQL命令的代码。例如: ```csharp // 伪代码:构建SQL命令 string sql = "SELECT * FROM Table WHERE Condition = :param1"; using (var cmd = new OracleCommand(sql, connection)) { // 假设parameters是ObservableCollection<DBParameter> foreach (var p in parameters) { cmd.Parameters.Add(p); } // ... 执行命令 } ``` 确保: - 参数名称与SQL语句中的占位符名称匹配(包括大小写,Oracle默认不区分,但占位符名称必须一致)。 - 避免在SQL语句中直接拼接字符串,以防止SQL注入和语法错误。 **总结解决方案:** 1. **检查SQL语法**:特别是ORA-00933错误,检查SQL语句的结尾是否正确,以及是否在子查询中不当地使用了ORDER BY。 2. **查看内部异常**:获取更详细的错误信息。 3. **日志记录**:确保记录完整的异常信息。 4. **参数化查询**:检查参数化查询的构建过程。 5. **备选方案**:尝试修改注册表(如果怀疑加密策略问题)。 如果问题仍然存在,请提供更多上下文,例如具体的SQL语句(或生成SQL的代码)和完整的异常堆栈信息。 §§相关问题§§ 1. 如何捕获WCF服务中的内部异常以便于调试? 2. 在Oracle数据库中,如何避免ORA-00933错误? 3. 在C#中,如何正确构建Oracle参数化查询? 4. 修改注册表禁用FIPS算法策略会有什么安全影响? </think>针对您遇到的`System.Reflection.TargetInvocationException`和`System.ServiceModel.FaultException<ExceptionDetail>`异常(包含ORA-00933错误),结合`ObservableCollection<DBParameter>`环境,以下是系统解决方案: ### 错误原因分析 1. **ORA-00933错误本质** Oracle错误代码`ORA-00933`表示SQL命令未正确结束,常见于: - SQL语句末尾有多余字符(如分号`;`) - 错误使用`ORDER BY`位置(如子查询内) - 无效的表连接语法 - 参数化查询拼接错误 2. **异常关联性** `TargetInvocationException`通常是底层异常的包装,而`FaultException`表明WCF服务层捕获到数据访问异常。两者共同指向数据库操作失败,通过`ObservableCollection<DBParameter>`传递参数时触发了ORA-00933[^1]。 --- ### 解决方案 #### 第一步:验证SQL语法(关键) 检查生成SQL语句的代码逻辑: ```csharp // 典型错误示例:结尾多出分号 string sql = "SELECT * FROM Users WHERE Name = :name;"; // 应删除分号 // 正确写法 string sql = "SELECT * FROM Users WHERE Name = :name"; ``` #### 第二步:检查参数化查询 确保`ObservableCollection<DBParameter>`参数与SQL占位符匹配: ```csharp var parameters = new ObservableCollection<DBParameter> { new DBParameter("name", OracleDbType.Varchar2, "John") }; // 验证占位符一致性 // SQL中必须使用 :name 而非 @name 或 ?name ``` #### 第三步:修改注册表(引用[1]方案) 针对`TargetInvocationException`: 1. 按`Win+R`输入`regedit` 2. 定位路径: `计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\FipsAlgorithmPolicy` 3. 将`Enabled`值改为`0` 4. 重启系统生效[^1] #### 第四步:捕获内部异常 添加详细日志记录真实错误: ```csharp try { // 数据库操作代码 } catch (FaultException<ExceptionDetail> ex) { // 记录内部异常消息 logger.Error($"ORA错误详情: {ex.Detail.InnerException?.Message}"); } ``` #### 第五步:Oracle特定语法检查 避免常见陷阱: - 子查询中禁用`ORDER BY` - 使用标准JOIN语法替代旧式逗号连接 - 参数名严格匹配(Oracle区分大小写) --- ### 预防措施 1. **SQL验证工具** 使用Oracle SQL Developer运行相同SQL,验证语法正确性 2. **参数化查询规范** ```csharp // 推荐使用OracleParameterCollection var cmd = new OracleCommand(sql); cmd.Parameters.AddRange(parameters.ToArray()); ``` 3. **更新驱动** 安装最新版ODP.NET(Oracle Data Provider) > **重要提示**:若上述步骤未解决,请检查WCF服务的`web.config`中数据库连接字符串的`Unicode=True`参数是否启用,缺失此配置可能引发字符集转换异常。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值