Hi,
Please can you advise the best way to map from an XDocument property type to an Oracle XMLType? I am mapping to a legacy database and have no control over the schema. It is Oracle 9i.
I have read that version 3 of nHibernate provides out the box functionality for this type of mapping. I am using version 3.1 with fluent mappings and I receive the following error when using the default map on a create:
System.ArgumentOutOfRangeException : Specified argument was out of the range of valid values. at Oracle.DataAccess.Client.OracleParameter.set_DbType(DbType value) at NHibernate.Driver.DriverBase.SetCommandParameters(IDbCommand cmd, SqlType[] sqlTypes) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Driver\DriverBase.cs: line 180 at NHibernate.Driver.DriverBase.GenerateCommand(CommandType type, SqlString sqlString, SqlType[] parameterTypes) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Driver\DriverBase.cs: line 136 at NHibernate.AdoNet.AbstractBatcher.Generate(CommandType type, SqlString sqlString, SqlType[] parameterTypes) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\AdoNet\AbstractBatcher.cs: line 78 at NHibernate.AdoNet.AbstractBatcher.PrepareBatchCommand(CommandType type, SqlString sql, SqlType[] parameterTypes) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\AdoNet\AbstractBatcher.cs: line 146 at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object id, Object[] fields, Boolean[] notNull, Int32 j, SqlCommandInfo sql, Object obj, ISessionImplementor session) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs: line 2616 at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object id, Object[] fields, Object obj, ISessionImplementor session) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs: line 3050 at NHibernate.Action.EntityInsertAction.Execute() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Action\EntityInsertAction.cs: line 59 at NHibernate.Engine.ActionQueue.Execute(IExecutable executable) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs: line 136 at NHibernate.Engine.ActionQueue.ExecuteActions(IList list) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs: line 125 at NHibernate.Engine.ActionQueue.ExecuteActions() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs: line 170 at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs: line 241 at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Event\Default\DefaultFlushEventListener.cs: line 20 at NHibernate.Impl.SessionImpl.Flush() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\SessionImpl.cs: line 1470
I got round this my writing my own user type which converts between an XDocument and a string:
/// <summary>The NHibernate SQL types for the columns mapped by this type.</summary> public SqlType[] SqlTypes { get { return (new SqlType[] { new StringClobSqlType() }); } }
/// <summary>The type returned by <c>NullSafeGet()</c>.</summary> public Type ReturnedType { get { return (typeof(XDocument)); } }
/// <summary>Retrieve an instance of the mapped class from a resultset.</summary> /// <param name="rs">a IDataReader</param> /// <param name="names">column names</param> /// <param name="owner">the containing entity</param> /// <returns>A Date object</returns> public object NullSafeGet(IDataReader rs, string[] names, object owner) { XDocument xDoc = null;
int columnIndex = rs.GetOrdinal(names[0]); if (!rs.IsDBNull(columnIndex)) { xDoc = XDocument.Parse((rs[columnIndex].ToString())); }
return (xDoc); }
/// <summary>Write an instance of the mapped class to a prepared statement.</summary> /// <param name="cmd">a IDbCommand</param> /// <param name="value">the object to write</param> /// <param name="index">command parameter index</param> public void NullSafeSet(IDbCommand cmd, object value, int index) { IDbDataParameter parameter = (IDbDataParameter)cmd.Parameters[index];
if (value == null) { parameter.Value = DBNull.Value; } else { XDocument xDoc = (XDocument)value; parameter.Value = xDoc.ConvertToString(); } }
This worked fine until the string was greater than 4000 characters in length. Now I get the error:
NHibernate.Exceptions.GenericADOException : could not insert: [XmlBlob#95586][SQL: INSERT INTO XMLBLOB (CAT_CODE, BLB_BLOB, BLB_ID) VALUES (?, ?, ?)] ----> Oracle.DataAccess.Client.OracleException : ORA-01461: can bind a LONG value only for insert into a LONG column
Any ideas are much appreciated.
|