使用大型CLOB从C#调用存储过程的问题

chi*_*oro 18 c# oracle stored-procedures clob system.data.oracleclient

我不是第一个遇到这些问题的人,并会在下面列出一些参考文章,但我仍在寻找合适的解决方案.

我需要从C#Web服务调用存储过程(Oracle 10g数据库).Web服务器安装了Oracle 9i客户端,我使用的是Microsoft System.Data.OracleClient.

该过程将XML作为CLOB.当XML超过4000字节(这可能是正常的用例)时,我偶然发现了以下错误:

ORA-01460 - 要求执行未实现或不合理的转换

我发现了这个,这个这个帖子.

此外,我发现了一个很有前途的解决方法,它不直接从C#调用存储过程,而是定义了一段匿名PL/SQL代码.此代码作为OracleCommand运行.XML嵌入为字符串文字,过程调用从该段代码中完成:

private const string LoadXml =
    "DECLARE " +
    "  MyXML CLOB; " +
    "  iStatus INTEGER; " +
    "  sErrMessage VARCHAR2(2000); " +
    "BEGIN " +
    "  MyXML := '{0}'; " +
    "  iStatus := LoadXML(MyXML, sErrMessage); " +
    "  DBMS_OUTPUT.ENABLE(buffer_size => NULL); " +
    "  DBMS_OUTPUT.PUT_LINE(iStatus || ',' || sErrMessage); " +
    "END;";
OracleCommand oraCommand = new OracleCommand(
    string.Format(LoadXml, xml), oraConnection);
oraCommand.ExecuteNonQuery();
Run Code Online (Sandbox Code Playgroud)

不幸的是,一旦XML超过32 KB左右,这种方法就会失败,这在我的应用程序中仍然很有可能.这次错误源于PL/SQL编译器,它说:

ORA-06550:第1行,第87列:PLS-00172:字符串文字太长

经过一些研究后我得出结论,用我的第二种方法解决问题是不可行的.

根据上述帖子,我有以下两种选择.

(第一篇帖子说有些客户是马车,但是我的(9i)不属于上述10g/11g版本的范围.)

你能否确认这是剩下的两个选择?还是有另一种方法可以帮助我吗?

只是为了澄清:该XML 不会最终被保存在任何表,但它是由插入基于XML内容的一些表中的一些记录存储过程的处理.

我对这两个选项的考虑:

  • 切换到ODP.NET很困难,因为我必须将它安装在到目前为止我没有系统访问权限的Web服务器上,并且因为我们可能还想在客户端上部署这段代码,所以每个客户端都必须安装ODP.NET作为部署的一部分.
  • 绕过表使得客户端代码变得更加复杂,并且在数据库上调整/扩展PL/SQL例程也需要付出相当大的努力.

chi*_*oro 13

我发现,另一种方式来解决这个问题!我的同事救了我的一天,指着我这个博客说:

在DbConnection上调用BeginTransaction时设置参数值.

它会更简单吗?该博客涉及到Oracle.DataAccess,但它的工作原理也一样System.Data.OracleClient.

在实践中,这意味着:

varcmd = new OracleCommand("LoadXML", _oracleConnection);
cmd.CommandType = CommandType.StoredProcedure;

var xmlParam = new OracleParameter("XMLFile", OracleType.Clob);
cmd.Parameters.Add(xmlParam);

// DO NOT assign the parameter value yet in this place

cmd.Transaction = _oracleConnection.BeginTransaction();
try
{
    // Assign value here, AFTER starting the TX
    xmlParam.Value = xmlWithWayMoreThan4000Characters;

    cmd.ExecuteNonQuery();
    cmd.Transaction.Commit();
}
catch (OracleException)
{
    cmd.Transaction.Rollback();
}
Run Code Online (Sandbox Code Playgroud)

  • 我对旧问题的看法是,没有旧问题.这不是一个论坛,而是一个Q/A网站,所以理想情况下,一个特定的问题只能找到一次并且答案附在其上. (2认同)
  • 更新链接:http://henbo.wordpress.com/2007/12/05/ora-01460-unimplemented-or-unreasonable-conversion-requested/ (2认同)