首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用大型CLOB从C#调用存储过程的问题

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

Stack Overflow用户
提问于 2010-08-24 15:15:47
回答 4查看 22.2K关注 0票数 21

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

我需要从C# web服务调用一个存储过程(Oracle10g数据库)。web服务器安装了Oracle9i客户端,我正在使用Microsofts System.Data.OracleClient

该过程将XML作为CLOB。当XML超过4000 Bytes (在正常用例中很可能如此)时,我发现了以下错误:

ORA-01460 -未实现或不合理的转换请求

我找到了的帖子。

此外,我找到了一个很有希望的解决方法,它不直接从C#调用存储过程,而是定义了一段匿名PL/SQL代码。此代码以OracleCommand的形式运行。XML是作为字符串文本嵌入的,过程调用是在这段代码中完成的:

代码语言:javascript
运行
复制
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();

不幸的是,当XML超过32 KBytes (在我的应用程序中仍然很有可能)时,这种方法就会失败。这一次的错误来自PL/SQL编译器,它说:

ORA-06550: line1,列87:PLS-00172:字符串文本过长

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

在上述职位之后,我有以下两种选择.

(https://stackoverflow.com/questions/2549259/exception-when-calling-stored-procedure-ora-01460-unimplemented-or-unreasonabl说,有些客户是有问题的,但我的(9i)不属于上述10g/11g版本。)

,你能确认这是剩下的两种选择吗?还是有别的办法帮我?

澄清一下: XML最终不会保存在任何表中,但它是由存储过程处理的,存储过程根据XML内容在某些表中插入一些记录。

我对这两种选择的考虑:

  • 切换到ODP.NET很困难,因为我必须将它安装在到目前为止还没有系统访问权限的web服务器上,而且我们还可能希望在客户端上部署这段代码,因此每个客户端都必须安装ODP.NET作为部署的一部分。
  • 对表的绕行会使客户端代码更加复杂,而且在数据库适应/扩展PL/SQL例程方面也需要付出相当大的努力。
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-08-25 14:11:53

我发现还有另一种解决问题的方法!我的同事帮了我的忙,把我指向这个博客,上面写着:

当BeginTransaction已经在DbConnection上被调用时,设置参数值。

能更简单点吗?这个博客与Oracle.DataAccess有关,但它对System.Data.OracleClient也同样有效。

在实践中,这意味着:

代码语言:javascript
运行
复制
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();
}
票数 15
EN

Stack Overflow用户

发布于 2013-07-08 09:25:17

在我的例子中,奇科多罗的解决方案行不通。我正在使用ODP.NET ( Oracle.DataAccess )。

对我来说,解决方案是使用OracleClob对象。

代码语言:javascript
运行
复制
OracleCommand cmd = new OracleCommand("LoadXML", _oracleConnection);
cmd.CommandType = CommandType.StoredProcedure;

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

//connection should be open!
OracleClob clob = new OracleClob(_oracleConnection);
// xmlData: a string with way more than 4000 chars
clob.Write(xmlData.ToArray(),0,xmlData.Length);
xmlParam.Value = clob; 

try
{
    cmd.ExecuteNonQuery();
}
catch (OracleException e)
{
}
票数 3
EN

Stack Overflow用户

发布于 2010-08-24 17:52:13

我想我搜索这个是为了让你得到便宜的分数,但这里有一个很好的解释:

http://www.orafaq.com/forum/t/48485/0/

基本上,您不能在字符串文本中使用超过4000个字符,如果需要执行更多操作,则必须使用存储过程。然后,您被限制在最大32 to,所以您必须“块”插入。布莱。

-Oisin

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3557995

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档