Posts tagged NHibernate

Compromises

Preface

The reality our our profession (mo matter whether you think it’s a craft or a trade or whatever) is that we are not always allowed to make the best and optimal decisions from technical perspective. There are situations when other factors are more important. These factors include things like:

  • what skills are there on the team mean to build particular piece of software
  • what assumptions and constraints are inherited from previous team who worked on that project
  • what client thinks about the solution you propose (yes, unfortunately from time to time clients do influent your technical decisions)

So, lest get to the point. Say you want to pursue the newest and hottest trends in software architecture and want to implement a CQRS/Event Sourcing solution, but one (or more) of things I’ve just listed is preventing you from doing it. You are suck with your favorite ORM for this project (hope it’s not for life). What do you do? Do you give up and build a CRUD solution? I hope you’re not. I’d like to show you one of the alternatives which helped me solve one particular problem.

Problem

Let’s start by asking why do you wanted to use CQRS/Event Sourcing in the first place. Probably because of increased testability, cleaner domain model code and more focused classes. We can achieve pretty good results in this categories by building a CQRS solution with 2 ORM-based models on top of single database. Let me explain the details.

Roles and data flow

The following image depicts the fundamental roles and the data flow in proposed architecture.

User interface is commands to invoke behavior. Commands are processed (since it is a compromise-driven version, command processing is probably synchronous) in the domain model. Because we are using ORM as a persistence engine, I don’t see anything particularly wrong in using Unit of Work pattern to implement collaboration between aggregate roots. After command completes, the whole Unit of Work is persisted by the ORM.

When user interface demands for data, the ORM is used to hydrate (fill with data) a different set of classes, the read model. In pure CQRS scenario, retrieving a data for a view would be a SELECT * operation. Here, since we have only one shared database, we have to create more advanced projections and joins. But that’s the stuff you would have to write anyway if you decided to create a CRUD solution.

Command side

The following diagram shows various roles present on the command side of the equation.

First, there is a command which is sent (as I said, probably synchronously) to the Command Executor object. This guy is responsible for finding a Command Handler for particular command. This is where you could happily use Service Locator and even @kkozmic won’t yell at you:) If he does however, please contact me. But finding a handler is not enough. Command Executor is also responsible for transaction semantics of command execution. It is his job to create a Unit of Work (depending on ORM you’ve chosen, it would be either ISession or some ObjectContext-derived class). Next, he executes the command by passing it to the Command Handler.

First thing that guy has to do is to find domain objects somehow before he’ll  be able to trigger their behavior. He does it via Repositories.

Query side

This is way easier. We have some DTOs here that are optimized to transport data to the UI. There DTOs are directly mapped to the database tables. Because there is one shared set of tables for both command and query side, mapping of tables to DTOs is more complicated than in typical CQRS solution. In might involve joins for example.

Finders are for the query side what Repositories are for the command side. Finders, however, doesn’t allow to modify any data.

Quick case study

Here you can download source code of small sample application demonstrating this approach. All you have to do to run it is set up a database and adjust query string in app.config file.

This is a simple banking application. There are two kinds of accounts: internal bank accounts (these does not need to have a balance  as they can always be debited or credited) and normal customer accounts (no overdrawn allowed).

The command side uses inheritance to model the nuances in account behavior, while the model on the query side contains one big DTO class for both types of account. The latter decision allows easy binding to the UI controls. It is a quite common pattern to flatten the inheritance structure and represent actual types using enumerated values.

Summary

While I am sure that full-blown CQRS it the approach for solving complex domain problems, it is often very hard to deploy, especially in case of legacy systems. The compromise solution I described may help you in those cases. Once people start seeing real benefits of having some of CQRS principles implemented, it could be easier to convince them to give Event Sourcing a try in the next iteration…

VN:F [1.9.22_1171]
Rating: 5.0/5 (7 votes cast)

Jak zwątpiłem w transakcje

Transakcje to fajna sprawa. Polubiłem je od pierwszego użycia. Zostałem oczarowany przez ich magiczną właściwość — zwalniają z myślenia o spójności danych. Cool, przecież nie lubię myśleć. Jeszcze bardziej byłem oczarowany, gdy odkryłem transakcje rozproszone. To dopiero jazda. Mogę coś “zapdejtować” na tej bazie, na tej drugiej bazie i jeszcze wrzucić komunikat do kolejki MSMQ i wszystko wykona się transakcyjnie — w całości lub wcale.

Od dłuższego czasu zaczynam jednak wątpić w transakcje, szczególnie te rozproszone. Zbyt często ja sam lub ktoś ze znajomych wpada przez nie w pułapkę bez wyjścia. Zamiast używać najodpowiedniejszej technologii, musimy wtedy wziąć taką, która współdziała z naszym sposobem zarządzania transakcjami.

Najczęstszym problemem, na który natrafiałem jest odbieranie i wysyłanie komunikatów do kolejek z jednoczesnym zapisem danych w bazie. Pierwsza rzecz, która przychodzi w takim wypadku do głowy, to transakcja, która obejmuje zarówno infrastrukturę kolejkową, jak i RDBMS. Pierwsza nie oznacza, niestety, najlepsza.

Nieodpowiednia technologia

Wymaganie transakcyjności w komunikacji z RDBMS i kolejkami pchnęło mnie kilka lat temu do wykorzystania SQL Server Service Broker jako kolejki komunikatów. Unikalną cechą Service Broker’a jest fakt, że żyjąc wewnątrz silnika bazodanowego, jest w naturalny sposób zintegrowany z mechanizmami transakcyjnymi SQL Server. Nie ma potrzeby stosowania (wolnych) transakcji rozproszonych, aby wysłać komunikat i zrobić przysłowiowy “apdejt”.

Niestety poza tą jedną zaletą, Service Broker ma bardzo wiele wad, z których największą jest brak dobrego gotowego API w C#, o modelu usługowym (np. WCF) nie wspominając. Jest bardzo trudny w użyciu i utrzymywaniu. Definitywnie był to zły wybór technologiczny, podyktowany jedynie chęcią zastosowania mechanizmu transakcji.

Niezgodność API

W każdym nietrywialnym systemie wykorzystuje się wiele zewnętrznych bibliotek. Bardzo rzadko pochodzą one od jednego dostawcy. Zdecydowanie częściej jest to mieszanka rozwiązań open source oraz COTS. Problem pojawia się, gdy dwie z bibliotek mają współpracować w ramach jednej transakcji. Weźmy jako przykład NHibernate i NServiceBus. Ten pierwszy posiada własną abstrakcję reprezentującą transakcje, podczas gdy pod spodem korzysta z transakcji ADO.NET. Ten drugi wykorzystuje transakcje System.Transactions do dostępu do MSMQ.

W przypadku użycia obu technologii w jednej transakcji, pojawia się problem, jak sprawić, aby każda z bibliotek mogła wykorzystywać swoje API odwołując się do tej samej fizycznej transakcji. W wypadku wspomnianej pary, jedynym rozwiązaniem jest pozwolić NHibernate używać zewnętrznych transakcji System.Transactions. Jest to jednak zamiana jednego problemu na inny. Do niedawna bowiem pojawiał się w NServiceBus wyciek pamięci, ponieważ zachowanie NHibernate w wypadku współpracy z System.Transactions jest bardzo słabo udokumentowane i łatwo o błąd wynikający z niezrozumienia.

Błedne implementacje transakcyjności

Jonathan Oliver opisał swoje testy kompatybilności różnych silników bazodanowych z transakcjami rozproszonymi na swoim blogu. Wnioski nie są optymistyczne: jedynie sterowniki do SQL Server i Oracle w pełni i bez problemów je obsługują.

Z drugiej strony nie dziwie się, że mniej płatne lub darmowe rozwiązania nie wspierają rozproszonych transakcji. Zdecydowana większość systemów radzi sobie bez nich, więc zysk (w sensie pieniędzy z licencji lub satysfakcji użytkowników) z implementacji wsparcia dla nich byłby znikomy.

Proste rozwiązanie

Rozwiązanie jest oczywiście proste. Wymaga jednak nieco innego podejścia do projektowania komunikacji. Wystarczy zadbać o to, aby każdy komunikat był

  • albo idempotentny (wielokrotne przetworzenie takiego komunikatu daje taki sam efekt, jak przetworzenie jednokrotne),
  • albo jednoznacznie identyfikowalny (unikalne ID).

Drugi przypadek można sprowadzić do pierwszego dodając rejestr przetworzonych komunikatów zawierający ich unikalne ID i przed obsłużeniem komunikatu sprawdzać, czy aby nie został przetworzony wcześniej.

Po spełnieniu któregoś z powyższych warunków zyskujemy możliwość rozłącznego zarządzania transakcją związaną z obieraniem komunikatu (MSMQ, ServiceBroker) oraz transakcją bazodanową. Ta pierwsza powinna być zatwierdzana dopiero po zatwierdzeniu tej drugiej. Powoduje to, że mamy pewność, iż każdy komunikat zostanie przetworzony co najmniej raz. Z drugiej strony idempotentność gwarantuje nam, że skutki wielokrotnego przetworzenia będą takie, jak jednokrotnego. Ostatecznie więc uzyskujemy semantykę dokładnie raz — taką samą jak przy zastosowaniu transakcji rozproszonych.

Praktyka

Dokładnie taki mechanizm zastosowałem w swoim ostatnim systemie. Pozwolił mi on na użycie klienta Service Broker (użycie tej kolejki było narzucone z góry) w połączeniu z NHibernate bez konieczności integracji obu technologii. Ponieważ transakcje były rozdzielone, klient kolejek nie musiał wiedzieć nic o dostępie do danych i vice versa. Prawdopodobnie zaoszczędziło mi to kilka dni pracy przy implementacji, testach i poprawianiu bugów w warstwie integracyjnej. Nauczyłem się także, że najlepszą strategią integracji technologii jest unikanie integracji technologii, kiedy to tylko możliwe.

VN:F [1.9.22_1171]
Rating: 5.0/5 (1 vote cast)

Entity Framework 4 a NHibernate

W minioną sobotę miałem przyjemność uczestniczyć w krakowskiej edycji Visual Studio Community Launch. Co prawda, jako jeden z organizatorów, nie jestem najlepszą osobą do obiektywnej oceny tego wydarzenia, ale moim zdaniem było super.

Podczas VSCL miałem okazję sprawdzić się także w roli prelegenta, prowadząc dwie piętnastominutowe mikroprezentacje dotyczące Entity Framework 4 oraz Windows Communication Foundation 4. Przykłady kodu dla obu prezentacji umieściłem na MSDN Code Gallery odpowiednio tutaj i tutaj. Zapewne duża część z Was nie była na konferencji, dlatego postanowiłem owe przykłady omówić tutaj, na blogu. Dziś – EF4.

W obu przypadkach starałem się wpleść prezentację nowych funkcji danej technologii w jakąś większą historię. Dla Entity Framework tą większą historią jest możliwość współdzielenia (części) modelu z aplikacją napisaną w NHibernate.

Design

Solution wygląda tak:

Znajdują się w nim dwie aplikacje: obsługa zamówień (Orders) oraz bank (Accounts). Obie aplikacje składają się z prostego programu demonstrującego działanie, modelu domeny (Model) oraz obsługi persystencji (DataAccess). Współdzielony fragment to Parties – projekt niezależny od technologii persystencji (bez referencji do NHibernate lub EF) zawierający implementację podmiotów (osób fizycznych i organizacji).

POCO

Jednym z celów nowej wersji Entity Framework było wsparcie dla budowy modeli POCO (Plain Old CLR Object). Dlaczego jest to takie ważne? Ponieważ właśnie obsługa POCO pozwala wykorzystywać w EF klasy, które nie były napisane konkretnie z myślą o nim oraz, patrząc z drugiej strony, pozwala wykorzystać klasy napisane specjalnie dla EF w innych kontekstach. POCO daje nam komfort braku zależności od frameworku ORM na poziomie modelu domeny – coś, czego nie sposób przecenić. Dla przykładu, klasa Party reprezentująca podmiot wygląda tak:

public class Party
{
   public virtual int Id { get; protected set; }
   public virtual Address Address { get; protected set; }

   protected Party(Address address)
   {
      Address = address;
   }

   protected Party()
   {
   }
}

Lazy Loading

Leniwe ładowanie (lazy loading) jest kolejnym wielkim nieobecnym z pierwszej wersji EF, który doczekał się implementacji w wersji drugiej (czwartej). Jest ono jednak domyślnie wyłączone. Aby je włączyć, należy dodać do konstruktora kontekstu następującą linię:

ContextOptions.LazyLoadingEnabled = true;

Wszystko jednak ma swoją cenę. Ceną, którą płacimy za obsługę leniwego ładowania w EF jest konieczność „wirtualizacji” wszystkich property klas modelu. Jest to niezbędne, ponieważ EF w trakcie działania systemu generuje dynamicznie klasę dziedziczącą po naszej. Nie jest to jednak wielki problem, ponieważ NHibernate ma analogiczne wymaganie. Możemy więc spokojnie przywyknąć do myśli, że standardem dla ORM jest konieczność deklarowania wirtualnych property.

Value Objects

Value Objects są nazywane w EF „Complex Type”. Ot, taka fanaberia ludzi z Microsoft. Complex Type w EF może być modyfikowalny. Ja osobiście jednak odradzałbym to ze wszystkich. Niemodyfikowalność Value Object jest bardzo ważną cechą, m.in. ułatwiającą testowanie.

Ponieważ dla Complex Type EF nie prowadzi change tracking’u (sprawdzenie, czy należy zaktualizować bazę wykonywane jest za pomocą porównania wartości aktualnych i pobranych), nie ma sensu wirtualizacja properties CT. Znowu, jest to zgodne z tym, jak ja pracuje z NHibernate. Moje Value Objects muszą być jak najbardziej niezależne kontekstu bazodanowego. Jedyne na co się mogę (i niestety muszę) zgodzić to pusty konstruktor z widocznością protected. Zarówno EF, jaki NHibernate go wymagają. Efektem tego zestawu wymagań jest klasa Address będąca Value Objectem reprezentującym adres podmiotu:

public class Address
{
   public string Street { get; private set; }
   public string BuildingNumber { get; private set; }
   public string City { get; private set; }
   public string Country { get; private set; }

   protected Address()
   {
   }

   public Address(string street, string buildingNumber, string city, string country)
   {
      Street = street;
      BuildingNumber = buildingNumber;
      City = city;
      Country = country;
   }
}

Enkapsulacja

Enkapsulacja to zawsze dobra rzecz. Nie inaczej jest w wypadku modelu domeny. Upublicznianie getterów (a broń Boże setterów) właściwości jest prostą drogą do degradacji naszego modelu do roli prostych struktur danych. A przecież nie o to nam wszystkim chodzi. Z tego powodu bardzo się zmartwiłem po przeczytaniu na MSDN opisu wymagań dla POCO w EF. Wynika z niego (chyba, że ja źle rozumiem), że aby leniwe ładowanie działało, wszystkie właściwości klasy muszą być „public virtual”.

Na szczęście przeglądając sieć natknąłem się na wzmiankę, iż wystarczy „protected virtual”. Postanowiłem sprawdzić. Jakaż była moja radość, gdy okazało się, że wszystko działa. W kontekście enkapsulacji EF4 ma analogiczne wymagania, co NHibernate. Yupi:-)

Klasa Account jest świetnym przykładem enkapsulacji dla kolekcji: lista operacji związanych z kontem nie może być modyfikowana bezpośrednio, ale jedynie poprzez wywołania Credit lub Debit:

public class Account
{
   //...
   public decimal Balance { get; protected set; }
   protected virtual IList<Operation> Operations { get; set; }

   //...
   public virtual void Debit(decimal amount, string title)
   {
      if (Balance - amount < 0)
      {
         throw new InvalidOperationException();
      }
      var op = new Operation(-amount, title);
      Operations.Add(op);
      Balance -= amount;
   }

   public virtual void Credit(decimal amount, string title)
   {
      var op = new Operation(amount, title);
      Operations.Add(op);
      Balance += amount;
   }
}

Podsumowanie

Druga edycja Entity Framework jest o niebo lepsza od poprzedniej. Właściwie mogę powiedzieć z czystym sumieniem, że jest nawet używalna w kontekście Domain-Driven Design. Cieszy mnie to niezmiernie, bo lubię mieć wybór. Pluralizm to dobra rzecz. Czy rozważam przesiadkę z NHibernate na EF? Na pewno nie w tej wersji. Przewaga NH w przypadku bardziej skomplikowanych kwestii jest jeszcze zbyt duża. Z drugiej strony nie potrzebuję (i nie będę potrzebował) wszystkich tych kwestii związanych z obsługą architektur n-tier, w które Microsoft pakuje tyle pary.

Jeśli jednak EF będzie się rozwijać w tak szybkim tempie, jest wysoce prawdopodobne, że wersja 6.0 będzie stanowić groźną konkurencje dla NHibernate także w kontekście DDD.

VN:F [1.9.22_1171]
Rating: 4.0/5 (2 votes cast)

Automatic domain model persistence – halfway through

Just a quick note. There was no new post yesterday because I was busy implementing automatic persistence for domain model concept-proof. In the previous post I was writing about private field automapping. Since then I managed to implement a bunch of other concepts, including composite elements.

My fork of FluentNHibernate (automapping-fields branch) on github was updated with the most current code version.

DDDSample.NET ‘AutoPersistence’ branch uses the modified FNH to persists its domain model and it works! Without a single mapping file!

So, if everything works fine, why ‘halfway through’? That is because the code is very, very dirty and needs much work before it can be used in production.

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)

Using FluentNHibernate to automaticaly persist your domain model

Yesterday I came across the idea of totally automating domain persistence. There are out there plenty of convention-based persistence frameworks for ActiveRecord (like the Ruby on Rails one), but there is no equivalent solution for the Domain Model (as defined by Eric Evans Blue Book).

Your first thought may be that it is because domain model mapping is complicated. In fact many folks who write about Domain Model point the complexity of mapping as a key difference between DM and AR — the latter is supposed to be limited to one-to-one table to class mapping.

I disagree. In my opinion the difference lies in set of conventions and patterns used to create AR or DM models. While AR uses classes, public properties and relations, DM has its own: entities, value objects, aggregates and so on. The complexity level is comparable when sticking to DM patterns which greatly limit the set of mapping choices. This is the path I want to go.

So, my initiative is to implement Domain Model’s conventions and patterns using FluentNHibernate. I want my persistence mapping be generated straight from domain model without any external help. I want to define my conventions which will limit the possibilities so that automatic mapping is possible. In order to do this I will have to add some metadata to the model, which itself is a nice idea because it will make my models more expressive.

Every journey starts with a first step. I started with the following requirement/story

Private (and possibly readonly) fields can be automatically mapped if there is a corresponding read-only property.

This is not supported out-of-the-box by FluentNHibernate, so I had to fork it and change it. FNH uses a set of rules to map all the features of persistent class. These rules (IAutoMapper implementations) are governed by AutoMapper class. My modification extends the property mapping rule (AutoMapProperty class) so that is uses a set of access strategies to infer the access method of particular property instead of hard-coding property access. Currently (as it is a proof-of-concept) the only supported strategies are Property (formerly built-in) and CamelCase. You can download the modified version of FNH from here (GitHub).

I will be updating a DDDSample.Net branch (I have to create a new one;-)) with results of my work. The next step would be probably relations between aggregates and within an aggregate.

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)