【问题标题】:System.AccessViolationException - Oracle client toolsSystem.AccessViolationException - Oracle 客户端工具
【发布时间】:2014-12-17 04:39:00
【问题描述】:
Framework Version: v4.0.30319 
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
Stack:
  at Oracle.DataAccess.Client.OracleParameter.SetStatus(Int32)
  at Oracle.DataAccess.Client.OracleParameter.PreBind(Oracle.DataAccess.Client.OracleConnection, IntPtr, Int32, Boolean)
  at Oracle.DataAccess.Client.OracleCommand.ExecuteNonQuery()

我的应用程序因此异常而崩溃。 上下文是:我们正在尝试执行一个接受两个参数的存储过程,我们正在对命令文本中的参数使用名称绑定。

例子:

OraCommand.CommandText = "begin LOAD_UTILS.TRUNCATE_TABLE(:a1,:a2); end;"
OraCommand.Parameters.Add(New OracleParameter("a1", OracleDbType.Varchar2, 1000))
OraCommand.Parameters(0).Direction = ParameterDirection.Input
OraCommand.Parameters(0).Value = params(2)
OraCommand.Parameters.Add(New OracleParameter("a2", OracleDbType.Varchar2, 1000))
OraCommand.Parameters(1).Direction = ParameterDirection.Input
OraCommand.Parameters(1).Value = params(3)

我观察到的奇怪之处是,我们在 for 循环中运行这些语句以进行一定次数的重试,以防万一出现任何错误,OraCommand 是一个实例变量,因此参数集合不会被清除。

在第 1 次迭代中:正在添加参数 a1、a2
在迭代#2 中:前两个参数已经存在,我们再次添加名称为 a1 和 a2 的参数。 ...

没有看到问题,当我在每次迭代开始时清除参数集合时,但我无法提出导致问题的理论,有什么想法吗?

【问题讨论】:

  • 你的意思是,你尝试将相同的参数传递给一个过程两次,你想知道为什么它不允许?
  • @MikeJM OracleCommand 参数集合接受具有相同名称的参数对象,我试图推断这是否导致我在尝试运行执行 ExecuteNonQuery 函数时访问冲突异常

标签: c# .net oracle oraclecommand


【解决方案1】:

您正在使用 ODP.Net,它的工作方式是,.Net C# API 只是在 C 中公开其服务层的包装器,它与 OCI(Oracle 调用接口)通信,主要是访问冲突异常来自他们的服务层或 OCI,因为在托管代码 (.Net C#) 中存在访问冲突 (AV) 并不可行,因此 CLR 不允许这样做。调试问题的更简单方法是使用 Windbg,加载符号,它会为您指出导致问题的确切方法,这将是非托管代码,但挑战是您将拥有最多公开的发布版本符号,这没有多大帮助,其他选择是将代码问题发布到 Oracle Technet,ODP.Net 开发人员可以在其中提供解决方法和修复。但是在此之前,我认为您的代码存在某些问题:

在循环中,以下行每次都会添加一个新参数 a1 和 a2

OraCommand.Parameters.Add(New OracleParameter("a1", OracleDbType.Varchar2, 1000))
OraCommand.Parameters.Add(New OracleParameter("a2", OracleDbType.Varchar2, 1000))

您在预期中遇到的行为,因为只有在创建新参数之后,您才在索引 0 和 1 处设置值和方向,每次都相同,在每次迭代中,您最终都会添加两个新参数OracleCommand 对象和弄乱内部结构的地方,因为您所做的是不正确的。正确的方法是在循环中遵循代码:

OracleParameter A1 = OracleParameter("a1", OracleDbType.Varchar2, 1000)
A1.Direction = ParameterDirection.Input
A1.Value = params[2]
OracleCommand.Parameters[0] = A1;

OracleParameter A2 = OracleParameter("a2", OracleDbType.Varchar2, 1000)
A1.Direction = ParameterDirection.Input
A1.Value = params[3]
OracleCommand.Parameters[1] = A2;

实际上,您的代码中的另一个奇怪之处是使用以下代码访问集合之类的数组:

OraCommand.Parameters(0).Value = params(2)

这在 C# 中是不可能的,你必须使用方括号 [],在我看来你必须使用 VB.Net,因为即使你 new 也不正确,它不是 C# 中的 New

【讨论】:

    【解决方案2】:

    @Mrinal Kamboj 你是对的,代码在 VB.NET 中;尝试执行 ExecuteNonQuery 时引发异常。我尝试了 WinDbg,这就是它所提供的:

    【讨论】:

    • 这个 Stack Trace 没什么用,它有所有的 MS 调用,而不是一个 Oracle 调用,你不会使用 Release 符号得到它,请考虑解决方案的其他部分,你当前实现不正确
    猜你喜欢
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多