3

我一直在尝试使用 Fluent NHibernate 1.2.0.712 针对 Oracle 10g 映射 clob 字段。我正在使用 System.Data 提供程序,因为它默认可用,并且由于以前的客户端问题而试图避免添加对 ODP.Net 的引用。

但是,当我尝试插入具有映射 clob 属性的实体时,出现错误:

ORA-01461: 只能绑定 LONG 值以插入 LONG 列

我尝试通过使用以下约定来解决此问题,并使用 [StringLength(4000)] 装饰适当的属性:

public class StringLengthConvention : AttributePropertyConvention<StringLengthAttribute>
{
    protected override void Apply(StringLengthAttribute attribute, IPropertyInstance instance)
    {
        instance.Length(attribute.MaximumLength);
    }
}

这没有用。

然后我使用“TEXT”、“CLOB”和“clob”值尝试了以下操作。都没有工作:

    public class plaparteMappingOverride : IAutoMappingOverride<plaparte>
    {
        public void Override(AutoMapping<plaparte> mapping)
        {
           Map(x => x.disposiciones).CustomSqlTypeIs("TEXT");
        } 
    }

除了将 ODP 添加为提供程序之外,是否有人对此修复有进一步的建议?

4

1 回答 1

0

供将来参考:这篇文章完美地描述了导致此错误的原因以及如何解决它。

ORA-01461: 只能绑定 LONG 值以插入 LONG 列

此错误不是很有帮助,并且很可能会导致有关 oracle 补丁等的主题。实际上,这是 microsoft oracle 客户端驱动程序的错误。驱动程序错误地推断出正在保存的字符串的列类型,并试图强制服务器将 LONG 值更新为 CLOB/NCLOB 列类型。错误行为的原因更加模糊,只有在满足以下所有条件时才会发生。

  1. 当我们设置 IDbDataParameter.Value = (长度为 4000 > length > 2000 的字符串)
  2. 当我们设置 IDbDataParameter.DbType = DbType.String
  3. 当 DB Column 是 NCLOB/CLOB 类型时

不幸的是,NHibernate 2.0 的默认行为是完全按照上述方式进行的,这使得在使用 nhibernate 和 oracle 时更有可能遇到这个丑陋的错误。

博客文章中提供的解决方案:自定义 NHibernate Oracle 驱动程序:

/// <summary>
/// Initializes the parameter.
/// </summary>
/// <param name="dbParam">The db param.
/// <param name="name">The name.
/// <param name="sqlType">Type of the SQL.
protected override void InitializeParameter(System.Data.IDbDataParameter dbParam, string name, global::NHibernate.SqlTypes.SqlType sqlType)
{
    base.InitializeParameter(dbParam, name, sqlType);

    //System.Data.OracleClient.dll driver generates an exception
    //we set the IDbDataParameter.Value = (string whose length: 4000 > length > 2000 )
    //when we set the IDbDataParameter.DbType = DbType.String
    //when DB Column is of type NCLOB/CLOB
    //The Above is the default behavior for NHibernate.OracleClientDriver
    //So we use the built-in StringClobSqlType to tell the driver to use the NClob Oracle type
    //This will work for both NCLOB/CLOBs without issues.
    //Mapping file will need to be update to use StringClob as the property type
    if ((sqlType is StringClobSqlType))
    {
        ((OracleParameter)dbParam).OracleType = OracleType.NClob;
    }
}
于 2012-08-17T13:03:36.090 回答