Od pewnego czasu zamiast stosowania mapowań za pomocą plików XML zacząłem używać FluentNHibernate. Mimo początkowego sceptycznego podejścia przełamałem się, a dobitnie nastąpiło to wtedy, kiedy zacząłem używać konwencji.
Jedną z fajniejszych, która odrazu spowodowała pozytywne nastawienie do FNH jest konwencja IIdConvention. Pozwala na zautomatyzowanie mapowania klucza głównego. Dlaczego? Od zawsze stosuję klucze pojedyncze oparte na typie int lub long, gdzie wartość jest wyliczana algorytmem hilo. Otóż nie bardzo mi się podoba kiedy NHibernate niezależnie od typu obiektu nadawał im wartość z tej samej puli, zaczynając od jakiejś z góry nieustalonej liczby.
Na początku w tabeli hibernate_unique_key definiowałem dla każdego typu osobną kolumnę, gdzie był trzymany parametr next_hi, ale to była utopia. Później znalazłem opcję, że można doklejać własny WHERE do zapytania odpytującego tabelę hibernate_unique_key. Niestety tworzenie pliku mapowania pochłaniało kilka linii na samo skonfigurowanie klucza głównego. Milion możliwośći na błąd...
Dzięki FNH i konwencjom mam spokój i o nic nie muszę się martwić. Dodatkowo każdy typ posiada swoją pulę w wierszach. Struktura tabeli hibernate_unique_key jest następująca:
CREATE TABLE [dbo].[hibernate_unique_key](
[entity] [nvarchar](50) NOT NULL,
[next_hi] [int] NOT NULL,
CONSTRAINT [PK_hibernate_unique_key] PRIMARY KEY CLUSTERED
(
[entity] ASC
)
) ON [PRIMARY]
A teraz konwencja:
public class PrimaryKeyConvention : IIdConvention
{
public bool Accept(IIdentityInstance id)
{
return true;
}
public void Apply(IIdentityInstance id)
{
id.Column("ID");
id.UnsavedValue("0");
id.GeneratedBy
.HiLo("20", x =>
{
x.AddParam("where", string.Format("entity = '{0}'", id.EntityType.Name));
});
}
}
... i już nie muszę klepać tych opasłych linii kodu dla każdej klasy. Podłączam konwencję i robi się samo :)
Ok, no prawie. Jedyne co muszę zrobić to wraz z nowym typem muszę dodać kolejny wiersz do tabeli hibernate_unique_key, gdzie w kolumnie entity znajdzie się nazwa typu obiektu.
PS
Muszę pomyśleć nad jakimś automatycznym uzupełnianiu tej tabeli przy starcie aplikacji :)