Search code examples
nhibernatefluent-nhibernatenhibernate-mappinglegacy

How do you map a composite id to a composite user type with Fluent NHibernate?


i'm working w/ a legacy database is set-up stupidly with an index composed of a char id column and two char columns which make up a date and time, respectively. I have created a ICompositeUserTypefor the date and time columns to map to a single .NET DateTime property on my entity, which works by itself when not part of the id. i need to somehow use a composite id with key property mapping that includes my ICompositeUserType for mapping to the two char date and time columns. Apparently w/ my version of Fluent NHibernate, CompositeIdentityPart doesn't have a CustomTypeIs() method, so i can't just do the following in my override:

mapping.UseCompositeId()
    .WithKeyProperty(x => x.Id, CommonDatabaseFieldNames.Id)
    .WithKeyProperty(x => x.FileCreationDateTime)
    .CustomTypeIs<FileCreationDateTimeType>();

is something like this even possible w/ NHibernate let alone Fluent? I haven't been able to find anything on this.

UPDATE:

after reading the NHibernate documentation more carefully, i found out that NHibernate does support component composite IDs, but it doesn't look like it supports custom types (i.e. IUserType and ICompositeUserType) for composite IDs. Also, the version of Fluent i have doesn't have support for NHibernate's support of component composite IDs (see issue 387 and issue 346). i will probably try and upgrade my entire solution, see if it works, and post an answer to my own question if it does... unless someone can tell me w/o me having to do that... 8o)


Solution

  • NHibernate doesn't support the use of IUserType or ICompositeUserTypes for composite IDs. It does, however, support component composite IDs, but Fluent NHibernate has limited support for this. From what i could see in the source code, it doesn't allow you to specify the column names for the component properties like NHibernate allows. I had to give-up for now and just create two string fields that the two string date fields in the database could map to seperately, and then have a DateTime? property that translated the two string properties. Props to HeavyWave for their comment: "Although, I think you should just map each column to its own field and provide additional property that combines them."

    mapping.CompositeId()
                .KeyProperty(x => x.Id, CommonDatabaseFieldNames.Id)
                .KeyProperty(x => x.FileCreationDateString, CommonDatabaseFieldNames.FileCreationDate)
                .KeyProperty(x => x.FileCreationTimeString, CommonDatabaseFieldNames.FileCreationTime);