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,
Quelle est votre méthode actuelle de génération d'ID? Oracle sécuences, ou .... _? – rebelliard
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