Fluent NHibernate och automappa komponenter

Posted by Kenny Eliasson | Posted in , , , | Posted on 13:28

Nu så vart man "äntligen" tillbaka på jobbet efter en skön jul och nyårsledighet.

Det första jag tog tag i var att generera den nya tabeller till våran rapporteringsapplikation. Jag har tidigare berättat om hur jag använder Fluent NHibernate för att göra detta, men denna gången störde jag mig mycket på att jag var tvungen att göra många mappningar "by-hand" via IAutoMappingOverride för att jag skulle mappa Components.

En Component är en egen klass men datan för klassen ligger i föräldrens tabell.
T.ex. en MetaData-klass som innehåller Created, Version m.m.
Denna MetaData-klass vill man inte mappa till en helt egen tabell utan man mappar min MetaData-klass till kolumner i dess föräldrer. I detta fall mappar jag min Report-entitet till en tabell med namnet Reports som även innehåller kolumner för MetaData-klassen.

Problemet är ju att MetaData-klassen ligger som en property på Reports-klassen och därmed kommer mappas som en "one-to-many" referens. För att komma runt detta innan har jag ofta mappat komponenter för hand, men detta tröttnade jag på idag och bestämde mig för att se hur man kommer runt detta.

Efter lite eftersökningar hittade jag hur säger vilka typer som skall hanteras som komponenter.

På Fluent Nhibernates AutoPersistanceModel finns det en metod som heter Setup(). Via denna kan man bestämma vilka klasser som skall hanteras som komponenter.

.Setup(s => { s.IsComponentType = type => typeof (MetaData) })

Nu fick jag MetaData-klassen att vara mappad som en komponent. Men hur jag gör om så att alla mina befintliga komponenter mappas in på samma sätt?

.Setup(s => { s.IsComponentType = type => typeof (MetaData) || type => typeof(Component2) || etc.. etc.. })

Att göra som ovan med flera "eller" alternativ kan ju bli lite grötigt.

Det jag gjorde istället var att jag gjorde ett tomt interface, ett så kallat marker-interface

public interface IComponent { }

och gjorde så att alla mina komponent-klasser ärvde av det. Sen ändrade jag Setup-koden till

.Setup(s => { s.IsComponentType = type => typeof (IComponent).IsAssignableFrom(type) })

Detta jag tycker jag är sjukt smidigt :)

Om man inte vill använda marker interfaces kan man ju t.ex. använda sig av attribut men då måste man använda reflection för att läsa av klasserna.

Vad tycker ni, vettig lösning? Vad tycker ni om Marker-interfaces vs. Attribut?

Comments (0)

Skicka en kommentar