fluent-nhibernate icon indicating copy to clipboard operation
fluent-nhibernate copied to clipboard

User type convention isn't applied to primary keys

Open svallory opened this issue 12 years ago • 4 comments

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.

svallory avatar Sep 26 '13 15:09 svallory

Can you give an example use case when you want a user type convention for primary key?

chester89 avatar Sep 26 '13 15:09 chester89

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.

svallory avatar Sep 26 '13 18:09 svallory

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);

Trinition avatar Sep 27 '13 16:09 Trinition

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.

svallory avatar Sep 27 '13 16:09 svallory