I need to use Fluent-nHibernate against a table with a composite primary key (Azure Table, primary keys being (PartitionKey,RowKey) and I would like to map them with corresponding properties on the entity (or with a component property, if easier)
my table would look like:
{
PartitionKey PK,
RowKey PK,
[..]
}
and the entity
public class MyRecord
{
public virtual string PartitionKey{get;set;}
public virtual string RowKey{get;set;}
[...]
}
My current projet uses a custom nHibernate Driver targeting AzureTable.
I managed to make it work with ClassMap or XML mappings. Therefore I am sure that the driver is working. Furthermore, the azure table HTTP requests are correct using classmaps or XML declarations.
However I really need conventions, so this isn’t an acceptable solution.
Finally, there is always the option to map only RowKey as a PK, even if the Datastore use (PartitionKey,RowKey). It works too, However it’s not really satisfying as it introduces an unicity handling mismatch between nHibernate and the underlying datastore.
UPDATE:
I tried to build a custom IIdentityConvention. The IIdentityInstance.Column() method takes into account only the first call.
However, if I use reflection to add both columns to the underlying mapping field, the configuration build fails with an XML validation exception (attribute ‘class’ required)
I got it working today, but it’s not pretty. It also doesn’t use a convention. As I understand conventions, they’re really meant for tweaking things after the main mapping has occurred. Adding mappings I believe is considered out of scope for conventions.
In my project I have a generic automapping-based initialization procedure that knows nothing of types, but has dependency-injected mapping overrides for composite keys. Not exactly your scenario, but it’s a similar problem.
The way I got this to work through reflection was to get hold of the appropriate AutoPersistenceModel object. If you have code looking like this:
The AutoPersistenceModel object would be m.AutoMappings.First()
From here, it’s pretty serious reflection work, culminating in a call to a protected method inside FluentNHibernate. Here’s the code I’m using: