代码改变世界

NHibernate+Oracle 遇到ORA-01461和ORA-01084及解决方法

2010-03-13 20:10  无常  阅读(3120)  评论(0编辑  收藏  举报

如果使用到Oracle的CLOB字段,那么NHibernate会遇到很诡异的“ORA-01461:仅可以插入LONG列的LONG值赋值”错误。关于此错误的分析和解决方法在这里(http://blog.csdn.net/pojianbing/archive/2008/08/09/2789426.aspx)有详细的介绍,实现NHibernate的自定义类型IUserType接口 :

    public abstract class PatchForOracleLobField : IUserType
    {
        public PatchForOracleLobField()
        {
        }
        public bool IsMutable
        {
            get { return true; }
        }
        public System.Type ReturnedType
        {
            get { return typeof(String); }
        }
        public SqlType[] SqlTypes
        {
            get
            {
                return new SqlType[] { NHibernateUtil.String.SqlType };
            }
        }
        public object DeepCopy(object value)
        {
            return value;
        }
        public new bool Equals(object x, object y)
        {
            return x == y;
        }
        public int GetHashCode(object x)
        {
            return x.GetHashCode();
        }
        public object Assemble(object cached, object owner)
        {
            return DeepCopy(cached);
        }
        public object Disassemble(object value)
        {
            return DeepCopy(value);
        }
        public object NullSafeGet(IDataReader rs, string[] names, object owner)
        {
            return NHibernate.NHibernateUtil.StringClob.NullSafeGet(rs, names[0]);
        }
        public abstract void NullSafeSet(IDbCommand cmd, object value, int index);
        public object Replace(object original, object target, object owner)
        {
            return original;
        }
    }
    public class OracleClobField : PatchForOracleLobField
    {
        public override void NullSafeSet(IDbCommand cmd, object value, int index)
        {
            if (cmd is OracleCommand)
            {
                //CLob、NClob类型的字段,存入中文时参数的OracleDbType必须设置为OracleDbType.Clob
                //否则会变成乱码(Oracle 10g client环境)
                OracleParameter param = cmd.Parameters[index] as OracleParameter;
                if (param != null)
                {
                    param.OracleType = OracleType.Clob;// 关键就这里啦
                    param.IsNullable = true;
                }
            }
            NHibernate.NHibernateUtil.StringClob.NullSafeSet(cmd, value, index);
        }
    }

 

用此方法解决了CLOB字段2000-4000字的问题,可是今天又遇到了个新的“ORA-01084: OCI 调用中的参数无效”错误,google了一下,大概是说CLOB字段如果为null或’’时就会出这个错。

解决的办法:

将OracleClobField.NullSafeSet中的

if (cmd is OracleCommand) ….

改为

if ((cmd is OracleCommand) && !string.IsNullOrEmpty(value as string))

 

如果值是空或者空字符串的话就让NHibernate当默认的varchar2处理。

 

from:http://wuchang.cnblogs.com