代码改变世界

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

  无常  阅读(3134)  评论(0编辑  收藏  举报

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示