3

映射clobs我一直在嘗試使用Fluent NHibernate 1.2.0.712針對Oracle 10g映射clob字段。我使用System.Data提供程序,因爲它默認情況下可用,並且由於之前的客戶端問題而試圖避免添加對ODP.Net的引用。使用Fluent NHibernate,Oracle 10g和OracleClientConfiguration.Oracle10

然而,當我嘗試使用映射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作爲提供者之外,是否有人對此修復有進一步的建議?

+0

我不要了微軟供應商,但ODP.NET你不需要爲CLOB的任何特殊,他們只是映射爲普通字符串(有一個例外,它試圖將空字符串插入爲空而不是空clob)。你的'plaparte.disposiciones'屬性是一個字符串嗎? – cremor

回答

0

以備參考:this post完美描述了導致此錯誤的原因以及如何解決該錯誤。在博客中提供

ORA-01461: can bind a LONG value only for insert into a LONG column

This error is not very helpful and goggling it will most likely result in topics regarding oracle patches and the like. In reality this is a bug with the microsoft oracle client driver. The driver mistakenly infers the column type of the string being saved, and tries forcing the server to update a LONG value into a CLOB/NCLOB column type. The reason for the incorrect behavior is even more obscure and only happens when all the following conditions are met.

  1. when we set the IDbDataParameter.Value = (string whose length is : 4000 > length > 2000)
  2. when we set the IDbDataParameter.DbType = DbType.String
  3. when DB Column is of type NCLOB/CLOB

Unfortunately NHibernate 2.0's default behavior is to do exactly the above, making it quite more likely to run into this ugly bug when using nhibernate and 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; 
    } 
} 
+0

雖然這可能在理論上回答這個問題,[這將是更可取的](http://meta.stackexchange.com/q/8259)在這裏包括答案的基本部分,並提供鏈接供參考。 – Aaronaught

+0

剛剛做到了,謝謝指出。 – Lodewijk