This article was moved to MDriven Wiki – Custom OR Mapping
We had this issue from Rich W in the forum – he tried to do a custom OR mapping.
He wanted to pick a modeled attribute to be the primary key in the database.
This is how to accomplish this:
In Class1 we are going to make SomePK the primary key.
On Class1 we set PrimaryKey and PrimaryKeyMapper:
We also set the SaveAction on the attribute SomePK to Freeze – possible other values DBAssigned and None.
Doing this mean that we ourselves take responsibility that the key is set and that we do not allow for it to be changed once saved – as is normal for primary keys.
If we had DBAssigned – it will not be set on save – and it will be re-read from the DB once saved. This is for scenarios where you have AutoInc fields in the database.
Rich did all this correctly but could not get it to work – he got errors while trying to generate the database. At first I could not put my finger on why but then it dawned on me that we have an issue with the DefaultSuperClass.
The package may have a named DefaultSuperClass that all the other classes in the package inherit from. And this still has the default primary key mapping.
If you do not have a designed DefaultSuperClass – the auto generated class EcoModelRoot will assume its place in the standard OR mapping.
So the EcoModelRoot has a standard key named EcoId and the subclass Class1 has the SomePK attribute as primary key – that is both strange and not what Rich wanted – and this is also not supported – hence the error Rich got.
To handle this we need to instruct the OR mapper to do something about it. In this particular case the best thing is to skip the EcoModelRoot table. We do this by adding a DefaultORMappingBuilder to the PersistenceMapper:
We connect it to both NewMappingProvider and RunTimeMappingProvider of the PersistenceMapper (New is used in design time when doing the create and evolve, runtime is when the app executes):
So far we have really changed nothing – this is what would have happened anyway – but we have exposed the defaultORMappingBuilder so that we can tweak it:
The most important tweak is ChildMapRootClass – this means that EcoModelRoot – or if you have another modeled DefaultSuperClass will not get a table of its own – it will be mapped into the child classes. The other tweaks are just for show – I do this because I personally think it looks better with primary keys that follow the pattern above (original value is <Name> and EcoKey).
So having this in place I can generate schema and get the following result:
Class1 has the SomePK has key – but the Class2 that we did not give any special primary key has the default <TableName>ID – namely Class2ID. Also note the single link back to class1 in the class2 table – it is named Class1ID.