Search code examples
c#oraclenhibernatefluent-nhibernatebatching

OracleDataClientBatchingBatcherFactory Throws Null Reference Exception


We're using NHibernate version 4.0.4.4000 and configuring it with FluentNHibernate version 2.0.3.0.

I'm trying to setup batching on an Oracle connection with the Oracle Data Client Batching Batcher Factory (OracleDataClientBatchingBatcherFactory) and using the following code to create NHConfiguration:

var cfg = new NHibernate.Cfg.Configuration().DataBaseIntegration(prop => {
        prop.BatchSize = 1000;
        prop.Batcher<OracleDataClientBatchingBatcherFactory>();
    });

Getting the following exception on session flush:

System.NullReferenceException: Object reference not set to an instance of an object.
   at NHibernate.AdoNet.OracleDataClientBatchingBatcher.SetArrayBindCount(Int32 arraySize)
   at NHibernate.AdoNet.OracleDataClientBatchingBatcher.DoExecuteBatch(IDbCommand ps) ...

It looks like SetArrayBindCount method is using reflection to set ArrayBindCount property in OracleCommand. This method throws a null reference exception.

Did anyone else experience the same problem? Am I missing something or it's a bug in OracleDataClientBatchingBatcher?

I do not get this problem when I use the SQL Client Batching Batcher Factory (SqlClientBatchingBatcherFactory)

var cfg = new NHibernate.Cfg.Configuration().DataBaseIntegration(prop => {
        prop.BatchSize = 1000;
        prop.Batcher<SqlClientBatchingBatcherFactory>();
    });

Any help will be greatly appreciated as this is currently blocking us.

Question Origin: https://groups.google.com/forum/#%21topic/nhusers/-rzStjZSxmI


Solution

  • Spending a hours I found that the root cause of the problem is that OracleDataClientBatchingBatcher isn't compatible with all Oracle connection drivers, supported by nHibernate. In my case it was NHibernate.Driver.OracleClientDriver which is in fact a wrapper of System.Data.OracleClient.Connection and System.Data.OracleClient.OracleCommand.

    public OracleClientDriver() :
            base(
            "System.Data.OracleClient",
            "System.Data.OracleClient, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", 
            "System.Data.OracleClient.OracleConnection", 
            "System.Data.OracleClient.OracleCommand") { }
    

    If you inspect OracleCommand class you'll see that it doesn't really contain the property 'ArrayBindCount'. In addition to this MSDN tells that classes from System.Data.OracleClient namespace are deprecated:

    This types in System.Data.OracleClient are deprecated and will be removed in a future version of the .NET Framework. For more information, see Oracle and ADO.NET.

    To solve the problem you have to choose a NHibernate.Driver.OracleManagedDataClientDriver as connection driver which is using Oracle ADO.NET. Here is a part of nHibernate config file that does this:

    <property name="connection.provider">
        NHibernate.Connection.DriverConnectionProvider
    </property>
    <property name="connection.driver_class">
        NHibernate.Driver.OracleManagedDataClientDriver
    </property>
    <property name="dialect">
        NHibernate.Dialect.Oracle10gDialect
    </property> 
    

    Also, you'll need to install Oracle.ManagedDataAccess package from NuGet

    PM> Install-Package Oracle.ManagedDataAccess

    This approach is working perfectly for me