Реализация hilo (или seqhilo) в NHibernate и Oracle - PullRequest
1 голос
/ 06 октября 2010

У меня есть база данных (которую я не могу изменить) с 6 таблицами в Oracle 11g. Все таблицы имеют искусственный столбец OID для идентификатора, и его тип RAW (16). Администратор БД ответил мне, что они в необработанном, а не целочисленном виде, так как идентификаторы будут уникальными во всех шести таблицах - и мы должны это гарантировать.

Я разрабатываю пользовательский интерфейс на C #, и для слоя данных я (пытаюсь) использовать NHibernate. Как я могу реализовать генератор идентификаторов таким образом, чтобы удовлетворить эти потребности?

Большое спасибо,

Педро Дуссо

Моя карта:

<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>

А мой код класса:

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;
            }
        }
    }
}

Я создаю объект Job, и они пытаются сохранить его в базе данных. Улов попытки

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)
{...}

Полное исключение:

{System.InvalidCastException: не удалось преобразовать значение параметра из Guid в байт []. ---> System.InvalidCastException: объект должен реализовывать IConvertible. в System.Convert.ChangeType (значение объекта, тип преобразование типа, поставщик IFormatProvider) в System.Data.OracleClient.OracleParameter.CoerceValue (значение объекта, MetaType destinationType) --- Конец внутренней трассировки стека исключений --- в System.Data.OracleClient.OracleParameter.CoerceValue (значение объекта, MetaType destinationType) в System.Data.OracleClient.OracleParameter.SetCoercedValueInternal (значение объекта, метатип MetaType) в System.Data.OracleClient.OracleParameterBinding.PrepareForBind (соединение OracleConnection, Int32 и смещение) в System.Data.OracleClient.OracleCommand.Execute (оператор OciStatementHandleHandle, поведение CommandBehavior, логическое значение needRowid, OciRowidDescriptor & rowidDescriptor, ArrayList & resultParameterOrdinals) в System.Data.OracleClient.OracleCommand.ExecuteNonQueryInternal (логическое значение needRowid, OciRowidDescriptor & rowidDescriptor) в System.Data.OracleClient.OracleCommand.ExecuteNonQuery () в NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery (IDbCommand cmd) в NHibernate.AdoNet.NonBatchingBatcher.AddToBatch (ожидание IExpectation) в NHibernate.Persister.Entity.AbstractEntityPersister.Insert (идентификатор объекта, поля объекта [], логическое значение [] notNull, Int32 j, SqlCommandInfo sql, объект obj, сеанс ISessionImplementor) в NHibernate.Persister.Entity.AbstractEntityPersister.Insert (идентификатор объекта, поля объекта [], объектный объект, сеанс ISessionImplementor) в NHibernate.Action.EntityInsertAction.Execute () в NHibernate.Engine.ActionQueue.Execute (исполняемый файл IExecutable) в NHibernate.Engine.ActionQueue.ExecuteActions (список IList) в NHibernate.Engine.ActionQueue.ExecuteActions () в NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions (сеанс IEventSource) в NHibernate.Event.Default.DefaultFlushEventListener.OnFlush (событие FlushEvent) в NHibernate.Impl.SessionImpl.Flush () в NHibernate.Transaction.AdoTransaction.Commit () в MetaManager.Data.Services.JobDataControl.Save (Job job) в C: \ Users \ Pedro_Dusso \ documents \ visual studio 2010 \ Projects \ MetaManager \ MetaManager.Data \ Services \ JobDataControl.cs: строка 45}

И, искренне, я не понимаю вашего первого подозрения. В базе данных у меня есть таблица JOB и таблица ETL_PROCESS. Их отношения как 1: n, JOB может иметь много процессов etl.

PS: я добавляю свою конфигурацию nhibernate, может быть, это поможет.

<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>

Ошибка при использовании ODP: {NHibernate.HibernateException: не удалось создать драйвер из NHibernate.Driver.OracleDataClientDriver. ---> System.Reflection.TargetInvocationException: исключение было сгенерировано целью вызова. ---> NHibernate.HibernateException: не удалось найти реализацию IDbCommand и IDbConnection в сборке Oracle.DataAccess. Убедитесь, что сборка Oracle.DataAccess находится в каталоге приложения или в глобальном кэше сборок. Если сборка находится в GAC, используйте элемент в файле конфигурации приложения, чтобы указать полное имя сборки.в NHibernate.Driver.ReflectionBasedDriver..ctor (String driverAssemblyName, String connectionTypeName, String commandTypeName) в NHibernate.Driver.OracleDataClientDriver..ctor () --- Конец внутренней трассировки стека исключений --- at System.RuntimeTypeHandle.CreateInstance (тип RuntimeType, логический publicOnly, логический noCheck, логический & canBeCached, RuntimeMethodHandleInternal & ctor, логический & bNeedSecurityCheck) at System.RuntimeType.CreateInstanceSlow (логическое publicOnly, логическое skipCheckThis, логическое fillCache) at System.RuntimeType.CreateInstanceDefaultCtor (логическое значение publicOnly, логическое значение skipVisibilityChecks, логическое значение skipCheckThis, логическое значение fillCache) в System.Activator.CreateInstance (Тип тип, логическое не публичное) в System.Activator.CreateInstance (Тип тип) в NHibernate.Connection.ConnectionProvider.ConfigureDriver (настройки IDictionary 2 settings) --- End of inner exception stack trace --- at NHibernate.Connection.ConnectionProvider.ConfigureDriver(IDictionary 2) в NHibernate.Connection.ConnectionProvider.Configure (настройки IDictionary 2 settings) at NHibernate.Connection.ConnectionProviderFactory.NewConnectionProvider(IDictionary 2) в NHibernate.Cfg.SettingsFactory.BuildSettings (свойства IDictionary`2) в NHibernate.Cfg.Configuration.BuildSettings () в NHibernate.Cfg.Configuration.BuildSessionFactory () в MetaManager.Data.SessionProvider.get_Session () в C: \ Users \ Pedro_Dusso \ documents \ visual studio 2010 \ Projects \ MetaManager \ MetaManager.Data \ SessionProvider.cs: строка 27 в MetaManager.Data.AttributeDataService.get_Session () в C: \ Users \ Pedro_Dusso \ documents \ visual studio 2010 \ Projects \ MetaManager \ MetaManager.Data \ Services \ AttributeDataService.cs: строка 33 по адресу MetaManager.Data. в Debug.Program.Main (String [] args) в C: \ Users \ Pedro_Dusso \ documents \ visual studio 2010 \ Projects \ MetaManager \ Debug \ Program.cs: строка 24 в System.AppDomain._nExecuteAssembly (сборка RuntimeAssembly, аргументы String []) в System.AppDomain.ExecuteAssembly (String assemblyFile, Evidence assemblySecurity, String [] args) в Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly () в System.Threading.ThreadHelper.ThreadStart_Context (состояние объекта) в System.Threading.ExecutionContext.Run (ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта, логическое значение ignoreSyncCtx) в System.Threading.ExecutionContext.Run (ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта) в System.Threading.ThreadHelper.ThreadStart ()}

Еще раз спасибо,

1 Ответ

1 голос
/ 06 октября 2010

RAW - это двоичный тип в Oracle, который очень хорошо отображается на уникальный идентификатор (16 байт == 128 бит)

Итак, определите свойство Id как Guid и используйте guid.comb в качествегенератор.

...