简体   繁体   English

在NHibernate和Oracle中实现hilo(或seqhilo)

[英]Implementing hilo (or seqhilo) in NHibernate and Oracle

I have a database (which I can not modify) with 6 tables in Oracle 11g. 我在Oracle 11g中有一个包含6个表的数据库(无法修改)。 All tables have a OID artificial column for ID, and its type is RAW(16). 所有表都有一个用于ID的OID人工列,其类型为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. DBA回答我,它们是原始数据,而不是整数,因为这样,ID在所有六个表中都是唯一的-我们必须保证这一点。

I'm developing the UI in C# and for data layer I'm (trying) to use NHibernate. 我正在用C#开发UI,对于数据层,我正在(尝试)使用NHibernate。 How can I implement the ID generator in a way that attends this necessities? 如何以这种必需的方式实现ID生成器?

Thanks very much, 非常感谢,

Pedro Dusso 佩德罗·杜索(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. 我正在创建一个Job对象,他们试图将其保存在数据库中。 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:无法将参数值从Guid转换为Byte []。 ---> System.InvalidCastException: Object must implement IConvertible. ---> System.InvalidCastException:对象必须实现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 在System.Data.OracleClient.OracleParameter.CoerceValue(对象值,MetaType destinationType)处System.Convert.ChangeType(对象值,类型conversionType,IFormatProvider提供程序)---内部异常堆栈跟踪的结尾---在System.Data。 System.Data.OracleClient.OracleParameter.SetCoercedValueInternal(Object值,MetaType metaType)的System.Data.OracleClient.OracleParameterBinding.PrepareForBind(OracleConnection连接,Int32&偏移量)处的OracleClient.OracleParameter.CoerceValue(对象值,MetaType destinationType) .OracleClient.OracleCommand.Execute(OciStatementHandle statementHandle,CommandBehavior行为,布尔NeedRowid,OciRowidDescriptor&rowidDescriptor,ArrayList&resultParameterOrdinals)位于System.Data.OracleClient.OracleCommand.ExecuteNonQueryInternal(Boolean needRowid,OciRowidDescriptor&RowidDescriptor.Oracle )在NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery(IDbCommand cmd)在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:\\Users\\Pedro_Dusso\\documents\\visual studio 2010\\Projects\\MetaManage NHibernate处的nate.AdoNet.NonBatchingBatcher.AddToBatch(IExpectation期望)(在NHibernate处为Object id,Object []字段,Boolean [] notNull,Int32 j,SqlCommandInfo sql,Object obj,ISessionImplementor会话)。 NHibernate.Engine.ActionQueue.Execute(IExecutable可执行文件)NHibernate.Engine.ActionQueue.Execute(IExecutable可执行文件)NHibernate.Engine.ActionQueue处的Persister.Entity.AbstractEntityPersister.Insert(对象ID,Object []字段,Object obj,ISessionImplementor会话) NHibernate.Engine.ActionQueue.ExecuteActions()位于NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource会话)位于NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent事件)处于NHibernate.Impl.SessionImpl C:\\ Users \\ Pedro_Dusso \\ documents \\ visual studio 2010 \\ Projects \\ MetaManage中的MetaManager.Data.Services.JobDataControl.Save(Job job)中的NHibernate.Transaction.AdoTransaction.Commit()中的.Flush() r\\MetaManager.Data\\Services\\JobDataControl.cs:line 45} r \\ MetaManager.Data \\ Services \\ JobDataControl.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. 在数据库中,我有一个JOB表和一个ETL_PROCESS表。 Their relationship is like 1:n, a JOB can have many etl processes. 它们的关系就像1:n,一个JOB可以有许多etl过程。

PS.: I'm adding my nhibernate configuration, maybe it help. 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>

Error using the ODP: {NHibernate.HibernateException: Could not create the driver from NHibernate.Driver.OracleDataClientDriver. 使用ODP时出错:{NHibernate.HibernateException:无法从NHibernate.Driver.OracleDataClientDriver创建驱动程序。 ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Reflection.TargetInvocationException:调用的目标引发了异常。 ---> NHibernate.HibernateException: The IDbCommand and IDbConnection implementation in the assembly Oracle.DataAccess could not be found. ---> NHibernate.HibernateException:在程序集Oracle.DataAccess中找不到IDbCommand和IDbConnection实现。 Ensure that the assembly Oracle.DataAccess is located in the application directory or in the Global Assembly Cache. 确保程序集Oracle.DataAccess位于应用程序目录或全局程序集缓存中。 If the assembly is in the GAC, use element in the application configuration file to specify the full name of the assembly. 如果程序集在GAC中,请使用应用程序配置文件中的元素指定程序集的全名。 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 在NHibernate.Driver.OracleDataClientDriver..ctor()处在NHibernate.Driver.ReflectionBasedDriver..ctor(String driverAssemblyName,String connectionTypeName,String commandTypeName)-内部异常堆栈跟踪的结尾-在System.RuntimeTypeHandle.CreateInstance(RuntimeType类型,布尔值publicOnly,布尔值noCheck,布尔值和canBeCached,RuntimeMethodHandleInternal&ctor,System.RuntimeType.CreateInstanceSlow(布尔值publicOnly,布尔值skipCheckThis,布尔值fillCache)位于System.RuntimeType.CreateInstanceDefaultCtor(布尔值布尔型,仅布尔值skipVisibilityChecks, NHibernate.Connection.ConnectionProvider.ConfigureDriver(IDictionary 2 settings) --- End of inner exception stack trace --- at NHibernate.Connection.ConnectionProvider.ConfigureDriver(IDictionary System.Activator.CreateInstance(Type type)的System.Activator.CreateInstance(Type type,Boolean nonPublic)填充缓存2 settings) --- End of inner exception stack trace --- at NHibernate.Connection.ConnectionProvider.ConfigureDriver(IDictionary 2设置)处 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:\\Users\\Pedro_Dusso\\documents\\visual studio 2010\\Projects\\MetaManager\\MetaManager.Data\\SessionProvider.cs:line 27 at MetaManager.Data.AttributeDataService.get_Session() in C:\\Users\\Pedro_Dusso\\documents\\visual studio 2010\\Projects\\MetaManager\\MetaManager.Data\\Services\\AttributeDataService.cs:line 33 at MetaManager.Data.AttributeDataService.Save(Attribute attribute) in C:\\Users\\Pedro_Dusso\\documents\\visual studio 2010\\Projects\\MetaManager\\MetaManager.Data\\Services\\AttributeDataService.cs:line 58 at Debug.Program.Main(String[] args) in C:\\Users\\Pedro_Dusso\\documents\\visual studio 2010\\Projects\\MetaManager\\Debug\\Program 2 settings) at NHibernate.Connection.ConnectionProviderFactory.NewConnectionProvider(IDictionary 2设置)处的ectionProvider.Configure(IDictionary 2 settings) at NHibernate.Connection.ConnectionProviderFactory.NewConnectionProvider(IDictionary )处的NHibernate.Cfg.SettingsFactory.BuildSettings(IDictionary`2属性) C:\\ Users \\ Pedro_Dusso \\ documents \\ visual studio 2010 \\ Projects \\ MetaManager \\ MetaManager.Data \\ SessionProvider.cs中的MetaManager.Data.SessionProvider.get_Session()处的Configuration.BuildSessionFactory():MetaManager.Data.AttributeDataService处的第27行。 C:\\ Users \\ Pedro_Dusso \\ documents \\ Visual Studio 2010 \\ Projects \\ MetaManager \\ MetaManager.Data \\ Services \\ AttributeDataService.cs中的get_Session():C:\\ Users中MetaManager.Data.AttributeDataService.Save(Attribute attribute)的第33行\\ Pedro_Dusso \\ documents \\ visual studio 2010 \\ Projects \\ MetaManager \\ MetaManager.Data \\ Services \\ AttributeDataService.cs:C:\\ Users \\ Pedro_Dusso \\ documents \\ visual studio 2010中Debug.Program.Main(String [] args)的58行\\ Projects \\ MetaManager \\ Debug \\ Program .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()} .cs:第24行,位于System.AppDomain._nExecuteAssembly(RuntimeAssembly程序集,String。] args,位于System.AppDomain.ExecuteAssembly(String assemblyFile,证据程序集安全性,String [] args),位于Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()在System.Threading.ExecutionContext.Run(ExecutionContext executeContext,ContextCallback回调,对象状态,布尔值ignoreSyncCtx)在System.Threading.ExecutionContext.Run(ExecutionContext执行上下文,ContextCallback回调,对象状态) ),位于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) RAW是Oracle中的二进制类型,可以很好地映射到唯一标识符(16字节== 128位)

So, define your Id property as Guid and use guid.comb as the generator. 因此,将您的Id属性定义为Guid并使用guid.comb作为生成器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM