"ORA-01460: 转换请求无法实现或不合理"及C#操作Blob总结

class BlobDemo
{
    private static readonly string ConnectionString =
           "Data Source=Tcco;User ID=scott;Password=tiger;";
    public void AddWithProcedure(string file)
        {
            if (File.Exists(file) == false)
            {
                return;
            }
            string strSql = "AddPhoto";
            using (OracleConnection conn = new OracleConnection(ConnectionString))
            {
                conn.Open();
                OracleCommand cmd = new OracleCommand(strSql, conn);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add(new OracleParameter("vPhoto", OracleType.Blob));
                cmd.Parameters[0].Value = File.ReadAllBytes(file);//A
                cmd.ExecuteNonQuery();
            }
        }
    //方法1
    public void AddWithSqlText(string file)
        {
            if (File.Exists(file) == false)
            {
                return;
            }
            //string strSql = "begin insert into blobdemo(Photo) values(:Photo);end;";//B
            string strSql = "insert into blobdemo(Pno,Photo) values(pno.nextval,:Photo)";

            using (OracleConnection conn = new OracleConnection(ConnectionString))
            {
                conn.Open();
                OracleCommand cmd = new OracleCommand(strSql, conn);
                cmd.Parameters.Add(new OracleParameter(":Photo", OracleType.Blob));
                cmd.Parameters[0].Value = File.ReadAllBytes(file);
                cmd.ExecuteNonQuery();
            }
        }
    //方法2
    public void AddWithProcedure2(string file)
        {
            if (File.Exists(file) == false)
            {
                return;
            }
            string strSql = "AddPhoto";
            using (OracleConnection conn = new OracleConnection(ConnectionString))
            {
                conn.Open();
                OracleCommand cmd = new OracleCommand(strSql, conn);
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add(new OracleParameter("vPhoto", OracleType.Blob));

                byte[] arr = null;
                using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    arr = new byte[fs.Length];
                    fs.Read(arr, 0, arr.Length);
                }
                //生成OracleLob类型
                OracleCommand cmd2 = conn.CreateCommand();

                OracleTransaction tx;
                tx = conn.BeginTransaction();

                cmd2.Transaction = tx;
                cmd2.CommandText = "declare xx blob; begin dbms_lob.createtemporary(xx, false, 0); :tempblob := xx; end;";
                cmd2.Parameters.Add(new OracleParameter("tempblob", OracleType.Blob));
                cmd2.Parameters["tempblob"].Direction = ParameterDirection.Output;

                cmd2.ExecuteNonQuery();

                OracleLob tempLob;

                tempLob = (OracleLob)cmd2.Parameters["tempblob"].Value;
                tempLob.BeginBatch(OracleLobOpenMode.ReadWrite);
                tempLob.Write(arr, 0, arr.Length);
                tempLob.EndBatch();
                //tx.Commit();

                cmd.Parameters[0].Value = tempLob;
                cmd.Transaction = tx;

                cmd.ExecuteNonQuery();
            }
        }
}

在调用存储过程(脚本如下)时出现上述错误AddPhoto,原因:
A处语句将byte[]数组赋给参数,在存储过程执行时,应该有一个转换(猜测):暂且称为byte[]到blob的转换,
而这个转换应该是plsql完成的,如果数组长度大于32767(外来,未证实)的话,就会报上述错误。
那么怎样避免这个错误呢?

方法1:不用存储过程,用sql语句
 
注:但不能有多个语句,如B处,否则还是报上述错误。
方法2:还是用存储过程,但在赋值前将byte[]转换成OracleLob类型

--创建表
create table BLOBDEMO
(
  PHOTO BLOB,
  PNO   NUMBER(18)
)
--创建序列
create sequence PNO
minvalue 1
maxvalue 9999999999999999999999999
start with 27
increment by 1
nocache;
--创建存储过程
create or replace procedure AddPhoto
(vPhoto in blob)
is
l_pno number(18);
begin
select pno.nextval into l_pno from dual;
insert into BlobDemo(pno,Photo) values(l_pno,vPhoto);
end;

 

posted on 2015-10-23 11:31  绝处而逢生  阅读(3665)  评论(0编辑  收藏  举报

导航