У меня есть база данных (которую я не могу изменить) с 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 ()}
Еще раз спасибо,