fluent-nhibernate
fluent-nhibernate copied to clipboard
User type convention isn't applied to primary keys
Hi,
Is it by design that a UserTypeConvention isn't applied to primary keys? If so, I think it should be advertised somewhere. If not, I just found a bug.
Can you give an example use case when you want a user type convention for primary key?
Sure!
I'm using Guids as primary keys. But I want to control the generation of the guid so I can create a pseudo-sequential guids, which makes indexes perform much better (at least on SQL Server, but I believe it's true for any database which use B-Trees for indexes).
Also, as a minor benefit I can strong type method's arguments to accept a PersonId or a CompanyId (both Guid subclasses) and even it you create a PersonId and CompanyId using the same Guid value, through overload I can make aPersonId != aCompanyId.
I'm doing exactly that (if I understand you correctly):
Table("tblMatters");
Id(x => x.Id, "MatterID")
.GeneratedBy.Custom("identity")//Identity() // TODO This overcomes a bug in FluentNHibernate that tries to force integral identity types when in fact NH supposrt custom types like ours; see https://github.com/jagregory/fluent-nhibernate/issues/230
.CustomType<BaseIdUserType<MatterId>>()
.UnsavedValue(0);
Yep. That's what I did too (well, almost). I'm using Auto mapping, so I created a UserTypeConvention to apply my custom types automatically. When it didn't work (took me hours to find the real issue) I implemented a IIdConvention to automatically apply the custom user type to PKs. Like this... (in case someone finds this tread with the same issue)
public class PrimaryKeyConvention : IIdConvention
{
public void Apply(IIdentityInstance instance)
{
instance.Column("id");
var type = instance.Type.GetUnderlyingSystemType();
if (type.Implements<IIdentity>())
{
if (type.IsSubclassOfOrEqualsTo<Identity<Guid>>())
instance.CustomType(typeof(GuidIdentityUserType<>).MakeGenericType(type));
else if (type.IsSubclassOfOrEqualsTo<Identity<int>>())
instance.CustomType(typeof(IntIdentityUserType<>).MakeGenericType(type));
}
}
}
Type.Implements and Type.IsSubclassOfOrEqualsTo are extension methods I created.