3

Oracle 10g に対して Fluent NHibernate 1.2.0.712 を使用して 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値をバインドできます

このエラーはあまり役に立たず、ゴグリングすると、オラクルのパッチなどに関するトピックが発生する可能性が高くなります。実際には、これは microsoft oracle クライアント ドライバーのバグです。ドライバーは、保存されている文字列の列の型を誤って推測し、サーバーに強制的に LONG 値を CLOB/NCLOB の列型に更新させようとします。正しくない動作の理由はさらに不明であり、次のすべての条件が満たされた場合にのみ発生します。

  1. IDbDataParameter.Value = (長さが 4000 > 長さ > 2000 の文字列) を設定した場合
  2. IDbDataParameter.DbType = DbType.String を設定すると
  3. DB カラムがタイプ 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 に答える