0

What is the best way to map UInt32 type to sql-server int type with NHibernate.

The value is a picture width/height so negative value are not make sense here.

But maybe I should use int because NHibenate doesn't support unassigned ints.

Fitzchak Yitzchaki
  • 9,095
  • 12
  • 56
  • 96

2 Answers2

3

You can map the column with an IUserType.

<class name="UnsignedCounter">
    <property name="Count" type="mynamespace.UInt32Type, mydll"  />
</class>

And the IUserType which maps UInt32? and UInt32.

class UInt32Type : IUserType
{
    public object NullSafeGet( System.Data.IDataReader rs, string[] names, object owner )
    {
        int? i = (int?) NHibernateUtil.Int32.NullSafeGet( rs, names[0] );
        return (UInt32?) i;
    }

    public void NullSafeSet( System.Data.IDbCommand cmd, object value, int index )
    {
        UInt32? u = (UInt32?) value;
        int? i = (Int32?) u;
        NHibernateUtil.Int32.NullSafeSet( cmd, i, index );
    }

    public Type ReturnedType
    {
        get { return typeof(Nullable<UInt32>); }
    }

    public SqlType[] SqlTypes
    {
        get { return new SqlType[] { SqlTypeFactory.Int32 }; }
    }

    public object Assemble( object cached, object owner )
    {
        return cached;
    }

    public object DeepCopy( object value )
    {
        return value;
    }

    public object Disassemble( object value )
    {
        return value;
    }

    public int GetHashCode( object x )
    {
        return x.GetHashCode();
    }

    public bool IsMutable
    {
        get { return false; }
    }

    public object Replace( object original, object target, object owner )
    {
        return original;
    }

    public new bool Equals( object x, object y )
    {
        return x != null && x.Equals( y );
    }
}
Lachlan Roche
  • 25,678
  • 5
  • 79
  • 77
  • There is a problem when converting from an uint Enum type with `NullSafeSet`: value can not be converted to a nullable type in this case. Use `uint? u = null; if (value != null) u = (uint)value;` instead – fmuecke Jul 02 '13 at 16:28
  • Also Equals does not properly work. A working version could be `public new bool Equals(object x, object y) { if (object.ReferenceEquals(x, y)) { return true; } if (x == null || y == null) { return false; } return (uint)x == (uint)y; }` – fmuecke Jul 03 '13 at 07:05
  • @fmuecke: in this case, `Equals` will always receive boxed values, so `object.ReferenceEquals` will always return false, and they will never be null. – vgru Oct 31 '14 at 10:28
2

I'm a year late, but since I had the same question and found a different answer I thought I'd add it. It seems simpler. Maybe it has a flaw I haven't discovered yet.

I'm using NHibernate 3.0, Visual Studio 2005, and .NET 2.0.x.

I found I could use .NET's UInt32 class and not include the type attribute in the hbm.xml.

// .NET 2.0 Property syntax
public class MyClass
{
   // NHibernate needs public virtual properties. 
   private UInt32 _Id;
   public virtual UInt32 Id { get { return (_Id); } set { _Id = value; } }
}


// hbml.xml
<class name ="MyClass">
   <id name="Id" />
</class>


// SQL to create the table
CREATE TABLE `PumpConnection` (
`Id` **INT**(10) **UNSIGNED** NOT NULL AUTO_INCREMENT,
)
Conner
  • 30,144
  • 8
  • 52
  • 73
Bill
  • 21
  • 1
  • Did you try `sql-type` to use schema generation? – Stefan Steinegger Jul 18 '12 at 05:12
  • Unsure if this is a flaw, but I tried something similarly simple and hit a problem for values > 2^31: on read, they were brought back through NH's pipeline somewhere as `Int64` (signed!) and became the negative (two's complement?) representation of the same bits--and then threw an exception because the negative representation didn't fit in the data type UInt32. I'm on NHibernate 5, and my particular mapping was this: `map.Component(x => x.Color, m => { m.Property(m => m.Value); });` Point being, I guess.... have you tried this for values > 2^31? – S'pht'Kr Nov 12 '19 at 18:41