Long strings in N-Hibernate with Oracle cause erro

2019-02-10 21:51发布

I am using oracle as db and fluent Nhibernate for mapping.

Below is my Object Class

 public class UserFieldEvent
    {
        public virtual int Id { get; set; }
        public virtual UserFieldBase UserField { get; set; }
        public virtual EventType EventType { get; set; }
        public virtual string EventScript { get; set; }
    }

The length of property EventScript can be from 0 to 4000. In the database I made the column type for EventScript a CLOB.

Below is my mapping Class:

public UserFieldEventMap()
        {
            Table("TBLDS_USERFIELDEVENT");
            Id(x => x.Id).GeneratedBy.Sequence("SEQDS_USERFIELDEVENT");
            Map(x => x.EventType).CustomType<EventType>();
            Map(x =>  x.EventScript).CustomSqlType("CLOB");
            References(x => x.UserField).Column("USERFIELDBASEID");
        }

Now whenever the length of EventScript is greater than 2000 I get the error "ORA-01461: can bind a LONG value only for insert into a LONG column ." while saving the object into database. Can anyone help on this.

1条回答
冷血范
2楼-- · 2019-02-10 22:33

This is a known issue with the .NET provided System.Data.OracleClient.OracleConnection driver. The fix is either to use the Oracle provided ODP.net client Oracle.DataAccess.Client.OracleConnection (see: http://nuget.org/packages/odp.net.x86/) or use the following workaround (referenced from: http://thebasilet.blogspot.be/2009/07/nhibernate-oracle-clobs.html).

public class CustomOracleDriver : OracleClientDriver
{
    protected override void InitializeParameter(System.Data.IDbDataParameter dbParam, string name, SqlType sqlType)
    {
        base.InitializeParameter(dbParam, name, sqlType);


        // System.Data.OracleClient.dll driver generates an ORA-01461 exception because 
        // 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.) IDbDataParameter.Value = (string whose length: 4000 > length > 2000 )
        //   2.) IDbDataParameter.DbType = DbType.String
        //   3.) 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 must be updated to use StringClob as the property type
        // See: http://thebasilet.blogspot.be/2009/07/nhibernate-oracle-clobs.html
        if ((sqlType is StringClobSqlType))
        {
            ((OracleParameter)dbParam).OracleType = OracleType.NClob;
        }
    }
}

You need to update your SessionFactory to use this driver, as well as update any of your clob mappings to use StringClob custom type

Map(x => x.EventType).CustomSqlType("Clob").CustomType("StringClob");
查看更多
登录 后发表回答