Issues calling stored procedure from C# with large CLOB

痞子三分冷 提交于 2019-11-28 08:19:43

I found that there is another way to work around the problem! My fellow employee saved my day pointing me to this blog, which says:

Set the parameter value when BeginTransaction has already been called on the DbConnection.

Could it be simpler? The blog relates to Oracle.DataAccess, but it works just as well for System.Data.OracleClient.

In practice this means:

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();
}

In my case, chiccodoro's solution did not work. I'm using ODP.NET ( Oracle.DataAccess ).

For me the solution is using OracleClob object.

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)
{
}

chiccodoro is right.

public static int RunProcedure(string storedProcName, IDataParameter[] parameters)
    {
        using (OracleConnection connection = new OracleConnection(connectionString))
        {
            int rowsAffected;

            OracleCommand command = new OracleCommand(storedProcName, connection);
            command.CommandText = storedProcName;
            command.CommandType = CommandType.StoredProcedure;
            foreach (OracleParameter parameter in parameters)
            {
                command.Parameters.Add(parameter);
            }
            connection.Open();

            try
            {
                // start transaction
                command.Transaction = connection.BeginTransaction();
                rowsAffected = command.ExecuteNonQuery();
                command.Transaction.Commit();
            }
            catch (System.Exception ex)
            {
                command.Transaction.Rollback();
                throw ex;
            }

            connection.Close();
            return rowsAffected;
        }
    }
x0n

I guess I just googled this for you to get cheap points, but there's a great explanation here:

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

Basically you cannot use more than 4000 chars in a string literal, and if you need to do more, you must use a stored procedure. Then, you are limited to 32KB at max so you have to "chunk" the inserts. Blech.

-Oisin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!