środa, 15 grudnia 2010

NHibernate 3 i QueryOver API

Całkiem niedawno pojawiła się nowa wersja NHibernate oznaczona numerem 3. Informacje co, gdzie i jak uległo zmianie można oczywiście znaleźć na głównej stronie projektu. Mi z tych wszystkich nowości najbardziej przypadło do gustu nowe API do wykonywania zapytań czyli QueryOver.
Ale zacznijmy od początku. Wykonując zapytanie do bazy danych z poziomu NHibernate 2 mieliśmy do dyspozycji 4 możliwości: Każda z nich ma swoje unikalne zalety przez co mogą istnieć równorzędnie. Ale nie o tym chciałem mówić. Zawsze najciekawsze wydawało mi się używanie Criteria API. Dzięki niemu w stosunkowo prosty obiektowy sposób otrzymujemy możliwość wykonywania zapytań na naszych encjach. Dodając do tego jeszcze użycie odpowiedniego IResultTransformer umieszczającego otrzymane informacje bezpośrednio w innym obiekcie niż wyszukiwany można uznać Criteria API za całkiem poręczne. Był w tym wszystkim tylko jeden zasadniczy minus. Deklaracja co i jak chcemy pobrać odbywała się poprzez napisy. Dajmy na to, że posiadamy encję zamówienia. Z zapytania potrzebujemy uzyskać jedynie id, nazwę klient, oraz jego adres, a wynik zapisać w przygotowanym obiekcie dto. Kod prezentuję się następująco.
OrderDto order = _session.CreateCriteria<Domain.Order>("o")
    .Add(Restrictions.IdEq(id))
    .SetProjection(Projections.ProjectionList()
        .Add(Projections.Property("o.Id"), "Id")
        .Add(Projections.Property("o.ClientName"), "ClientName")
        .Add(Projections.Property("o.Address"), "Address"))
    .SetResultTransformer(Transformers.AliasToBean<OrderDto>())
    .UniqueResult<OrderDto>();
Z tymi napisami da się żyć, jasne. Powiem nawet, że da się do tego przyzwyczaić. Ale używając QueryOver ta kwestia odchodzi do lamusa. Dzięki temu API otrzymujemy zamiast napisów statyczne typowanie, a tym samym zyskujemy Intellisense i informacje o błędach na poziomie kompilacji. Powyższy kod zostaje zatem zamieniony na:
OrderDto dto = null;
OrderDto order = _session.QueryOver<Domain.Order>()
    .Where(o => o.Id == id)
    .SelectList(list => list
        .Select(o => o.Id).WithAlias(() => dto.Id)
        .Select(o => o.ClientName).WithAlias(() => dto.ClientName)
        .Select(o => o.Address).WithAlias(() => dto.Address))
    .TransformUsing(Transformers.AliasToBean<OrderDto>())
    .SingleOrDefault<OrderDto>();
Co interesujące warto zwrócić uwagę na fakt, że QueryOver jest jedynie nakładką na Criteria API. Widać to choćby po sposobie deklarowania aliasów. Używany jest w nich pusty obiekt! Na początku byłem zaskoczony. Ale w sumie jedyne co na tym poziomie jest potrzebne to nazwa używanej właściwości, a reszta już tkwi w System.Linq.Expressions i wcześniej wykorzystywanej metodzie stanowiącej "magię" NHibernata ;]

Brak komentarzy:

Prześlij komentarz