Implementing hilo (or seqhilo) in NHibernate and Oracle

I have a database (which I can not modify) with 6 tables in Oracle 11g. All tables have a OID artificial column for ID, and its type is RAW(16). The DBA answered me that they are in raw and not in integer because this way the IDs will be unique in all six tables - and we must guarantee that.

I'm developing the UI in C# and for data layer I'm (trying) to use NHibernate. How can I implement the ID generator in a way that attends this necessities?

Thanks very much,

Pedro Dusso

My map is:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="MetaManager.Data.Job,MetaManager.Data" table="JOB" lazy="true">
    <id name="Oid" column="OID" type="Guid">
      <generator class="guid.comb" />
    </id>
    <property name="JobId" type="Decimal">
      <column name="JOB_ID" length="10" sql-type="number" not-null="true" />
    </property>
    <bag name="EtlProcesses" inverse="true" cascade="all-delete-orphan">
     <key column="JOB_ID"/>
      <one-to-many class="MetaManager.Data.EtlProcess,MetaManager.Data"/>
    </bag>
  </class>
</hibernate-mapping>

And my class code is:

namespace MetaManager.Data
{
    public class Job
    {
        public virtual Guid Oid { get; set; }
        public virtual decimal JobId { get; set; }
        private IList<EtlProcess> _EtlProcesses;
        public virtual IList<EtlProcess> EtlProcesses
        {
            get
            {
                if (_EtlProcesses == null)
                    _EtlProcesses = new List<EtlProcess>();
                return _EtlProcesses;
            }
            set
            {
                _EtlProcesses = value;
            }
        }
    }
}

I'm creating a Job object and them trying to save it in the database. The catch of try

Job job = new Job(1, "Test Job", DateTime.Now, DateTime.MaxValue, "A", "Dusso");

Guid retVal;
ITransaction transaction = null;
try
{
    transaction = Session.BeginTransaction();
    Session.SaveOrUpdate(job);

    if (transaction != null && transaction.IsActive)
       transaction.Commit(); //the exception is trow here!
    else
       Session.Flush();
       retVal = job.Oid;
}
catch(Exception ex)
{...}

The complete exception is:

{System.InvalidCastException: Failed to convert parameter value from a Guid to a Byte[]. ---> System.InvalidCastException: Object must implement IConvertible. at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) at System.Data.OracleClient.OracleParameter.CoerceValue(Object value, MetaType destinationType) --- End of inner exception stack trace --- at System.Data.OracleClient.OracleParameter.CoerceValue(Object value, MetaType destinationType) at System.Data.OracleClient.OracleParameter.SetCoercedValueInternal(Object value, MetaType metaType) at System.Data.OracleClient.OracleParameterBinding.PrepareForBind(OracleConnection connection, Int32& offset) at System.Data.OracleClient.OracleCommand.Execute(OciStatementHandle statementHandle, CommandBehavior behavior, Boolean needRowid, OciRowidDescriptor& rowidDescriptor, ArrayList& resultParameterOrdinals) at System.Data.OracleClient.OracleCommand.ExecuteNonQueryInternal(Boolean needRowid, OciRowidDescriptor& rowidDescriptor) at System.Data.OracleClient.OracleCommand.ExecuteNonQuery() at NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery(IDbCommand cmd) at NHiber nate.AdoNet.NonBatchingBatcher.AddToBatch(IExpectation expectation) at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object id, Object[] fields, Boolean[] notNull, Int32 j, SqlCommandInfo sql, Object obj, ISessionImplementor session) at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object id, Object[] fields, Object obj, ISessionImplementor session) at NHibernate.Action.EntityInsertAction.Execute() at NHibernate.Engine.ActionQueue.Execute(IExecutable executable) at NHibernate.Engine.ActionQueue.ExecuteActions(IList list) at NHibernate.Engine.ActionQueue.ExecuteActions() at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session) at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event) at NHibernate.Impl.SessionImpl.Flush() at NHibernate.Transaction.AdoTransaction.Commit() at MetaManager.Data.Services.JobDataControl.Save(Job job) in C:UsersPedro_Dussodocumentsvisual studio 2010ProjectsMetaManage rMetaManager.DataServicesJobDataControl.cs:line 45}

And sincerely I don't understand your first suspicious. In the database, I have a JOB table and a ETL_PROCESS table. Their relationship is like 1:n, a JOB can have many etl processes.

PS.: I'm adding my nhibernate configuration, maybe it help.

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
      <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
      <property name="dialect">NHibernate.Dialect.Oracle9Dialect</property>
      <property name="connection.driver_class">NHibernate.Driver.OracleClientDriver</property>
      <property name="connection.connection_string_name">MetaManager</property>
      <mapping assembly="MetaManager.Data"/>
    </session-factory>
  </hibernate-configuration>

Error using the ODP: {NHibernate.HibernateException: Could not create the driver from NHibernate.Driver.OracleDataClientDriver. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> NHibernate.HibernateException: The IDbCommand and IDbConnection implementation in the assembly Oracle.DataAccess could not be found. Ensure that the assembly Oracle.DataAccess is located in the application directory or in the Global Assembly Cache. If the assembly is in the GAC, use element in the application configuration file to specify the full name of the assembly. at NHibernate.Driver.ReflectionBasedDriver..ctor(String driverAssemblyName, String connectionTypeName, String commandTypeName) at NHibernate.Driver.OracleDataClientDriver..ctor() --- End of inner exception stack trace --- at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) at System.Activator.CreateInstance(Type type, Boolean nonPublic) at System.Activator.CreateInstance(Type type) at NHibernate.Connection.ConnectionProvider.ConfigureDriver(IDictionary 2 settings) --- End of inner exception stack trace --- at NHibernate.Connection.ConnectionProvider.ConfigureDriver(IDictionary 2 settings) at NHibernate.Connection.Conn ectionProvider.Configure(IDictionary 2 settings) at NHibernate.Connection.ConnectionProviderFactory.NewConnectionProvider(IDictionary 2 settings) at NHibernate.Cfg.SettingsFactory.BuildSettings(IDictionary`2 properties) at NHibernate.Cfg.Configuration.BuildSettings() at NHibernate.Cfg.Configuration.BuildSessionFactory() at MetaManager.Data.SessionProvider.get_Session() in C:UsersPedro_Dussodocumentsvisual studio 2010ProjectsMetaManagerMetaManager.DataSessionProvider.cs:line 27 at MetaManager.Data.AttributeDataService.get_Session() in C:UsersPedro_Dussodocumentsvisual studio 2010ProjectsMetaManagerMetaManager.DataServicesAttributeDataService.cs:line 33 at MetaManager.Data.AttributeDataService.Save(Attribute attribute) in C:UsersPedro_Dussodocumentsvisual studio 2010ProjectsMetaManagerMetaManager.DataServicesAttributeDataService.cs:line 58 at Debug.Program.Main(String[] args) in C:UsersPedro_Dussodocumentsvisual studio 2010ProjectsMetaManagerDebugProgram .cs:line 24 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()}

Thanks again,


RAW is a binary type in Oracle, which maps very well to a unique identifier (16 bytes == 128 bits)

So, define your Id property as Guid and use guid.comb as the generator.

链接地址: http://www.djcxy.com/p/19116.html

上一篇: NHibernate HiLo只要

下一篇: 在NHibernate和Oracle中实现hilo(或seqhilo)