views:

854

answers:

2

Using NH 2.0, I have a custom type. It is composed of four properties, so I implemented ICompositeUserType.

I want to specify length and precision for the string and decimal properties within the user type, to avoid specifying it with every usage in the mapping files.

But there is only a PropertyTypes property to implement, which returns IType. The funny thing is, the IUserType has a SqlTypes property, ICompositeUserType does not.

  • Do I have to implement both interfaces?
  • Do I have to implement a user type to wrap each sql-type I want to specify?
  • Or how can I specify the Sql type for a composite user type?

Thanks a lot.

+2  A: 

I recommend downloading source code for this type of digging (NH 2.0).

First take a look at TypeFactory.HeuristicType method, which builds the IType instance.

...
else if (typeof(ICompositeUserType).IsAssignableFrom(typeClass))
{
    type = new CompositeCustomType(typeClass, parameters);
}
else if (typeof(IUserType).IsAssignableFrom(typeClass))
{
    type = new CustomType(typeClass, parameters);
}
...

So if your custom type implements ICompositeUserType it gets instantiated as CompositeCustomType class. This eliminates the possibility to implement both ICompositeUserType and IUserType interfaces.

Now let's take a look into CompositeCustomType

public override SqlType[] SqlTypes(IMapping mapping)
{
    IType[] types = userType.PropertyTypes;
    SqlType[] result = new SqlType[GetColumnSpan(mapping)];
    int n = 0;
    for (int i = 0; i < types.Length; i++)
    {
        SqlType[] sqlTypes = types[i].SqlTypes(mapping);
        for (int k = 0; k < sqlTypes.Length; k++)
        {
            result[n++] = sqlTypes[k];
        }
    }
    return result;
}

So it takes your types returned from PropertyTypes and builds the SqlType for each property. This means that providing your own user type wrappers for each property will do the trick.

bbmud
You mean that I need to write a custom type for each property where I want to specify the sql type. I need to try this. I actually wanted to avoid it.
Stefan Steinegger
Thanks for the answer, but I found a much simpler solution. See my own answer if you are interested in it.
Stefan Steinegger
A: 

I found the solution, it is pretty simple. I have to create the NHibernate types using the TypeFactory:

public IType[] PropertyTypes
{
  get
  {
    return new []
    {
      TypeFactory.GetDecimalType(36, 18),
      TypeFactory.GetStringType(100)
    }
  }
}
Stefan Steinegger