I wonder how I could actually map an UInt16 value to a corresponding database type without a big fuzz.
We are working with Microsoft SQL Server Compact 3.5, NHibernate and FluentNHibernate for configuration.
Straight forward approach - will result in an error
public class Identificator
{
public Identificator( ushort componentType, ushort componentID ) { ... }
public virtual ushort ComponentType { get; protected set; }
public virtual ushort ComponentID { get; protected set; }
...
}
public class IdentificatorMapping : ClassMap<Identificator>
{
public IdentificatorMapping()
{
this.Map( x => x.ComponentType );
this.Map( x => x.ComponentID );
...
}
}
When actually creating a new object on the database ...
// Create Object
Identificator persistableObjectOK = new Identificator( 0x0001, 0x0001 );
// Persist it
ISession session = GetSession();
session.Save( persistableObjectOK );
... I'll get that error, which is OK, as SQL Server CE does not know unsigned types
FluentNHibernate.Cfg.FluentConfigurationException: An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.
System.ArgumentException: Dialect does not support DbType.UInt16
Using CustomSqlType - works partly
So, I went and forced NHibernate to take an integer which is 4 bytes long on the database and so should cover the data range of an UInt16
public class IdentificatorMapping : ClassMap<Identificator>
{
public IdentificatorMapping()
{
this.Map( x => x.ComponentType ).CustomSqlType( "INTEGER" );
this.Map( x => x.ComponentID ).CustomSqlType( "INTEGER" );
...
}
}
The result is working ... as long as I stay below 32767!
Above that value, the whole thing blows up.
The strange thing is that, up in the application it is unsigned 2 bytes. Down in the database it is signed 4 bytes.
Both should be sufficient to store up to 65536
However, NHibernate is not yet convinced. At some place down to the database it tries to convert UInt16 into Int16.
System.Convert.ToInt16(UInt16 value)
System.UInt16.System.IConvertible.ToInt16(IFormatProvider provider)
System.Data.SqlServerCe.Accessor.set_Value(Object value)
System.Data.SqlServerCe.SqlCeCommand.FillParameterDataBindings(Boolean verifyValue)
System.Data.SqlServerCe.SqlCeCommand.ExecuteCommand(CommandBehavior behavior, String method, ResultSetOptions options)
System.Data.SqlServerCe.SqlCeCommand.ExecuteNonQuery()
NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery(IDbCommand cmd)
NHibernate.Id.Insert.AbstractSelectingDelegate.PerformInsert(SqlCommandInfo insertSQL, ISessionImplementor session, IBinder binder)
NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] fields, Boolean[] notNull, SqlCommandInfo sql, Object obj, ISessionImplementor session)
NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] fields, Object obj, ISessionImplementor session)
NHibernate.Action.EntityIdentityInsertAction.Execute()
NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object entity, Object id, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
NHibernate.Impl.SessionImpl.FireSaveOrUpdate(SaveOrUpdateEvent event)
NHibernate.Impl.SessionImpl.SaveOrUpdate(String entityName, Object obj)
NHibernate.Engine.CascadingAction.SaveUpdateCascadingAction.Cascade(IEventSource session, Object child, String entityName, Object anything, Boolean isCascadeDeleteEnabled)
NHibernate.Engine.Cascade.CascadeToOne(Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
NHibernate.Engine.Cascade.CascadeAssociation(Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
NHibernate.Engine.Cascade.CascadeProperty(Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, Object parent, Object anything)
NHibernate.Event.Default.AbstractSaveEventListener.CascadeBeforeSave(IEventSource source, IEntityPersister persister, Object entity, Object anything)
NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object entity, Object id, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)
NHibernate.Impl.SessionImpl.Save(Object obj)
Concrete question: how could I say NHibernate not to do this conversion, but convert from UIn16 to Int32 instead?