Try fast search NHibernate

03 November 2010

ConfORM: understanding polymorphism (inheritance)

As first a simple example based on inheritance.
private class Entity
{
    public int Id { get; set; }
}

private class VersionedEntity : Entity
{
    public int Version { get; set; }
}

private class MyEntity : VersionedEntity
{
    public string Name { get; set; }
}
The class Entity and the class VersionedEntity are not part of my domain, they are there only because OOP stuff; in practice I don’t want a mapping for those two classes.

To make the matter a little bit more complicated I will add two others classes.
private class TimeVersionedEntity: Entity
{
    public byte[] UpdatedAt { get; set; }
}

private class MyOtherEntity : TimeVersionedEntity
{
    public string Name { get; set; }
}
To let ConfORM to discover which is the property represent the version you can implement a IPattern<MemberInfo> and add it to ObjectRelationalMapper.Patterns.Versions but that is only if you like to work a little bit more than necessary.

In this case the most short way, and the most strongly-typed, is using the ConfORM’s capability to understand the polymorphism. In practice:
var orm = new ObjectRelationalMapper();
orm.VersionProperty<VersionedEntity>(x => x.Version);
orm.VersionProperty<TimeVersionedEntity>(x => x.UpdatedAt);

That done you can continue as usual getting the mappings for your entities; In this case, for instance, it may mean:
var rootEntities = new[] { typeof(MyEntity),typeof(MyOtherEntity) };
orm.TablePerClass(rootEntities);

var mapper = new Mapper(orm);
var mappings = mapper.CompileMappingFor(rootEntities);

If you have to customize the mapping of versions properties, again you can do it class-by-class (working a lot) or again using the ConfORM’s capability to understand the polymorphism:
mapper.Class<VersionedEntity>(cm => cm.Version(x => x.Version, vm => vm.Column("Revision")));

mapper.Class<TimeVersionedEntity>(cm => cm.Version(x => x.UpdatedAt, vm =>
    {
        vm.Column(column =>
            {
                column.Name("LastUpdate");
                column.SqlType("timestamp");
            });
        vm.Generated(VersionGeneration.Always);
    }));

Now suppose that what you need is a special case where for a class inheriting from VersionedEntity, like above, you have to use another column name than “Revision” (like above). What you have to do is only specify your special case trusting in ConfORM capability to understand the polymorphism:
mapper.Class<VersionedEntity>(cm => cm.Version(x => x.Version, vm => vm.Column("Revision")));
mapper.Class<MySpecialEntity>(cm => cm.Version(x => x.Version, vm => vm.Column("Version")));

In this example I shown only a simple usage for the property representing the version for optimistic lock but you can apply the same concept to any property.

Are you ConfORM ?

1 comment:

  1. Can Version be long type? I try to use long as the type of Version, but it can not be recognized, even I specified version's sqltype is BigInt(MySql), when I load data, the exception is thrown. "Invalid Cast (check your mapping for property type mismatches); ".

    using Int everything is ok.

    ReplyDelete