2010-10-06 5 views
1

J'ai une base de données (que je ne peux pas modifier) ​​avec 6 tables dans Oracle 11g. Toutes les tables ont une colonne artificielle OID pour ID, et son type est RAW (16). Le DBA m'a répondu qu'ils sont bruts et non en nombres entiers parce que de cette façon, les identifiants seront uniques dans les six tableaux - et nous devons le garantir.Implémentation de hilo (ou seqhilo) dans NHibernate et Oracle

Je développe l'interface utilisateur en C# et pour la couche de données, je suis en train d'essayer d'utiliser NHibernate. Comment puis-je implémenter le générateur d'ID d'une manière qui répond à ces nécessités?

Merci beaucoup,

Pedro Dusso

Ma carte est:

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

Et mon code de classe est:

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

Je crée un objet Travail les essayant de l'enregistrer dans la base de données. Les prises de tenter

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

L'exception est complète:

{System.InvalidCastException: Impossible de convertir la valeur de paramètre d'un Guid à un octet []. ---> System.InvalidCastException: l'objet doit implémenter IConvertible. à System.Convert.ChangeType (valeur de l'objet, le type conversionType, fournisseur IFormatProvider) à System.Data.OracleClient.OracleParameter.CoerceValue (valeur de l'objet, métatype destinationType) --- Fin de trace de pile d'exception interne --- à System.Data.OracleClient.OracleParameter.CoerceValue (valeur d'objet, MetaType destinationType) à System.Data.OracleClient.OracleParameter.SetCoercedValueInternal (valeur d'objet, MetaType metaType) à System.Data.OracleClient.OracleParameterBinding.PrepareForBind (connexion OracleConnection, Int32 & offset) à System.Data.OracleClient.OracleCommand.Execute (OciStatementHandle instructionHandle, comportement CommandBehavior, Boolean needRowid, OciRowidDescriptor & rowidDescriptor, ArrayLis t & resultParameterOrdinals) à System.Data.OracleClient.OracleCommand.ExecuteNonQueryInternal (Boolean needRowid, OciRowidDescriptor & rowidDescriptor) à System.Data.OracleClient.OracleCommand.ExecuteNonQuery() à NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery (IDbCommand cmd) à NHibernate.AdoNet.NonBatchingBatcher.AddToBatch (attente IExpectation) à NHibernate.Persister.Entity.AbstractEntityPersister.Insert (Object id, Object [] champs, Boolean [] notNull, Int32 j, SqlCommandInfo sql, Object obj, Session ISessionImplementor) à NHibernate.Persister.Entity.AbstractEntityPersister.Insert (Object id, objets [] champs, Object obj, session ISessionImplementor) à NHibernate.Action.EntityInsertAction.Execut e() à NHibernate.Engine.ActionQueue.Execute (exécutable de IExecutable) à NHibernate.Engine.ActionQueue.ExecuteActions (liste IList) à NHibernate.Engine.ActionQueue.ExecuteActions() à NHibernate.Event.Default.AbstractFlushingEventListener. PerformExecutions (session IEventSource) à NHibernate.Event.Default.DefaultFlushEventListener.OnFlush (événement FlushEvent) à NHibernate.Impl.SessionImpl.Flush() à NHibernate.Transaction.AdoTransaction.Commit() à MetaManager.Data.Services. JobDataControl.Enregistrer (travail Job) dans C: \ Users \ Pedro_Dusso \ documents \ studio visuel 2010 \ Projects \ MetaManager \ MetaManager.Data \ Services \ JobDataControl.cs: ligne 45}

Et sincèrement je ne comprends pas votre premier suspect . Dans la base de données, j'ai une table JOB et une table ETL_PROCESS. Leur relation est comme 1: n, un travail peut avoir plusieurs processus etl. PS: J'ajoute ma configuration nhibernate, peut-être que ça aide.

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

erreur en utilisant l'ODP: {NHibernate.HibernateException: Impossible de créer le pilote à partir NHibernate.Driver.OracleDataClientDriver. ---> System.Reflection.TargetInvocationException: Une exception a été lancée par la cible d'un appel. ---> NHibernate.HibernateException: L'implémentation IDbCommand et IDbConnection dans l'assembly Oracle.DataAccess est introuvable. Assurez-vous que l'assembly Oracle.DataAccess se trouve dans le répertoire de l'application ou dans le Global Assembly Cache. Si l'assembly est dans le GAC, utilisez l'élément dans le fichier de configuration de l'application pour spécifier le nom complet de l'assembly. à NHibernate.Driver.ReflectionBasedDriver..ctor (String driverAssemblyName, String connectionTypeName, String commandTypeName) à NHibernate.Driver.OracleDataClientDriver..ctor() --- Fin de trace de pile d'exception interne --- à System.RuntimeTypeHandle .CreateInstance (type RuntimeType, Boolean publicOnly, Boolean nocheck, Boolean & canBeCached, RuntimeMethodHandleInternal & cteur, Boolean & bNeedSecurityCheck) à System.RuntimeType.CreateInstanceSlow (Boolean publicOnly, Boolean skipCheckThis, Boolean FillCache) à System.RuntimeType.CreateInstanceDefaultCtor (Boolean publicOnly, skipVisibilityChecks booléen, boolean skipCheckThis, boolean fillCache) à System.Activator.CreateInsta nce (type de type, booléen non publique) à System.Activator.CreateInstance (type Type) à NHibernate.Connection.ConnectionProvider.ConfigureDriver (IDictionary 2 settings) --- End of inner exception stack trace --- at NHibernate.Connection.ConnectionProvider.ConfigureDriver(IDictionary deux paramètres) à NHibernate.Connection.ConnectionProvider.Configure (IDictionary 2 settings) at NHibernate.Connection.ConnectionProviderFactory.NewConnectionProvider(IDictionary 2 réglages) à NHibernate.Cfg.SettingsFactory.BuildSettings (propriétés IDictionary`2) à NHibernate.Cfg.Configuration.BuildSettings() à NHibernate.Cfg.Configuration.BuildSessionFactory() à MetaManager.Data.SessionProvider.get_Session() dans C: \ Users \ Pedro_Dusso \ documents \ studio visuel 2010 \ Projects \ MetaManager \ MetaManager.Data \ SessionProvider.cs: ligne 27 à MetaManager.Data.AttributeDataService.get_Session() dans C: \ Users \ Pedro_Dusso \ documents \ visual studi o 2010 \ Projects \ MetaManager \ MetaManager.Data \ Services \ AttributeDataService.cs: ligne 33 à MetaManager.Data.AttributeDataService.Save (attribut Attribut) dans C: \ Users \ Pedro_Dusso \ documents \ studio visuel 2010 \ Projects \ MetaManager \ MetaManager.Data \ Services \ AttributeDataService.cs: ligne 58 à Debug.Program.Main (String [] args) dans C: \ Users \ Pedro_Dusso \ documents \ studio visuel 2010 \ Projects \ MetaManager \ Debug \ Program.cs: ligne 24 à System.AppDomain._nExecuteAssembly (assemblage RuntimeAssembly, String [] args) à System.AppDomain.ExecuteAssembly (String assemblyFile, Evidence assemblySecurity, String [] args) à Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context (état de l'objet) at System.Threading.ExecutionContext.Run (ExecutionContext executionContext, ContextCallback callback, Etat de l'objet, Boolean ignoreSyncCtx) at System.Threading.ExecutionContext.Run (ExecutionContext executionContext, rappel ContextCallback, état de l'objet) at System.Threading.ThreadHelper.ThreadStart()}

Merci encore,

+0

Quelle est votre méthode actuelle de génération d'ID? Oracle sécuences, ou .... _? – rebelliard

+1

Vous auriez pu utiliser une séquence oracle pour remplir les identifiants dans toutes les tables - cela garantira que les identifiants seront uniques dans les six tables. – andr

Répondre

1

RAW est un type binaire Oracle, qui associe très bien à un identifiant unique (16 octets == 128 bits)

Ainsi, définir votre propriété Id comme Guid et utiliser guid.comb comme générateur.

+0

Je vais essayer ça! –

+0

Enfin (après quelques efforts pour le configurer correctement ..) j'ai fait fonctionner NHibernate. Mais je reçois cette exception: "Impossible de convertir la valeur du paramètre d'un Guid à un Byte []". Est pas censé GUID et octet [] fonctionne bien ensemble? Merci encore! –

+0

Vous faites quelque chose de bizarre avec les types. Pouvez-vous poster votre cartographie? Vous ne devriez pas avoir de référence à l'octet [] –

Questions connexes