Artykuł

microsoft.com microsoft.com
kwi 24 2014
0

Szybki start z NHibernate w 5 krokach

ORM to w dzisiejszych czasach termin obowiązkowy dla każdego programisty, która ma jakąkolwiek styczność z bazami danych. Dzięki temu rozwiązaniu, w dużo prostszy sposób można zmapować istniejące struktury bazy danych z logiką biznesową aplikacji. Mocno się chyba nie pomylę, jeśli stwierdzę że w obrębie platformy .NET liczą się głównie dwa rozwiązania: Entity Framework oraz tytułowy NHibernate.

Osobiście od zawsze wolałem to pierwsze, ale tak się ostatnio potoczyły koleje losu, że w dość krótkim czasie musiałem się również zaznajomić z tym drugim. NHibernate to w pewnym sensie produkt dojrzalszy, który wywodzi się ze środowiska Javowego. Oba rozwiązania cechuje trochę inne podejście i osobiście wydaje mi się, że NHibernate jest jednak bardziej złożony, w dużej mierze przez początkowo toporną konfigurację. Mimo wszystko można go całkiem sprawnie i szybko okiełznać, czego przykładem będzie dalsza część niniejszego tekstu;-)

Tak jak mówi tytuł, całą implementację rozwiązania opartego o NHibernate sprowadzimy do 5 kroków. Poniżej cały przepis.

Krok 1 - konfiguracja bazy danych

Pracę rozpoczniemy od stworzenia bazy danych. Mamy teraz dwie możliwe opcje:

  • Stworzyć bazę danych w Microsoft SQL Management Studio
  • Utworzyć bazę danych z poziomu Visual Studio

Osobiście wybrałem ten drugi wariant, ponieważ w praktyce jest dużo szybszy i umożliwia nam stworzenie całego projektu w obrębie jednej aplikacji. Przy tworzeniu bazy danych stajemy przed kolejnym wyborem. Możemy bowiem utworzyć bazę danych przetrzymywaną w klasyczny sposób na serwerze, bądź też możemy wykorzystać rozwiązanie, w którym baza przechowywana jest lokalnie w pliku. Na potrzeby naszego skromnego projektu, druga opcja będzie zdecydowanie korzystniejsza.

Wszystkie potrzebne opcje znajdziecie w okienku Server Explorer. Wystarczy tylko kliknąć na przycisk Connect To Database, a następnie wybrać źródło danych (opcja Microsoft SQL Server Database File) oraz wskazać lokalizację pliku (jeśli nie istnieje, to zostanie utworzony).

Wykorzystując Server Explorer w łatwy sposób wygenerujemy sobie również Connection String, który po zaznaczeniu bazy danych znajdziemy w oknie Properties w miejscu oznaczonym kluczem Connection String.

Po utworzeniu bazy danych, za pomocą Server Explorera dodajemy do niej tabelę.

Poniżej kod SQL generujący strukturę tożsamą do tej widocznej na obrazku powyżej:

CREATE TABLE [dbo].[Person]
(
	[Id] INT NOT NULL PRIMARY KEY IDENTITY(1,1), 
    [FirstName] NVARCHAR(50) NULL, 
    [LastName] NVARCHAR(50) NULL, 
    [Age] INT NULL
)

Skrypt musimy zatwierdzić przyciskiem Update.

Wykorzystując Server Explorer możecie od razu dodać kilka przykładowych rekordów, dzięki czemu nasza tabela nie będzie pusta.

Krok 2 - konfiguracja projektu

Do pracy nad przykładem wykorzystałem Visual Studio Express 2013 for Web, dlatego też postanowiłem przygotować rozwiązanie oparte o ASP.NET MVC. W tym celu utworzyłem projekt pustej aplikacji webowej z referencjami do MVC.

Za pomocą NuGeta pobrałem również bibliotekę NHibernate. NuGet z automatu pobierze wszystkie niezbędne zależności.

Krok 3 - tworzenie logiki biznesowej

Kolejnym krokiem będzie utworzenie prostej logiki biznesowej, czyli klasy która będzie odzwierciedleniem tabeli Person w naszym kodzie. Dodajmy więc plik Person.cs o poniższej strukturze do katalogu Models:

namespace NHibernateMVC.Models
{namespace NHibernateMVC.Models
{
    public class Person
    {
        public virtual int Id { get; set; }
        public virtual string FirstName { get; set; }
        public virtual string LastName { get; set; }
        public virtual int Age { get; set; }
    }
}

Pamiętajcie oczywiście o tym, by przestrzeń nazw była zgodną z tą zastosowaną w Waszym projekcie.

Krok 4 - konfiguracja NHibernate

Przyszła pora na najważniejszy etap, czyli konfigurację NHibernate. Główny plik konfiguracyjny możemy umieścić zasadniczo w dowolnym miejscu projektu. Dla uproszczenia, w naszym przypadku będzie to główny katalog aplikacji. Plik konfiguracyjny musi się nazywać hibernate.cfg.xml i mieć zbliżoną do poniższej zawartość:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="connection.provider">
      NHibernate.Connection.DriverConnectionProvider
    </property>
    <property name="connection.driver_class">
      NHibernate.Driver.SqlClientDriver
    </property>
    <property name="connection.connection_string">
      Data Source=(LocalDB)\v11.0;AttachDbFilename=D:\NTest.mdf;Integrated Security=True;Connect Timeout=30
    </property>
    <property name="dialect">
      NHibernate.Dialect.MsSql2012Dialect
    </property>
  </session-factory>
</hibernate-configuration>

Przy założeniu ze wykorzystujecie bazę SQL Server, to do zmiany będzie Connection string (pisałem wcześniej o tym gdzie możecie go znaleźć) oraz ewentualnie dialekt (ja wykorzystuje bazę Microsoft SQL Server 2012 Express, jeśli korzystacie z innej wersji, odpowiedni dialekt znajdziecie tutaj).

W kolejnym kroku należy przygotować mapowanie dla naszej klasy Person. W tym celu tworzymy nowy plik XML w katalogu Models. W ramach konwencji, powinien się on nazywać Person.hbm.xml i mieć następującą zawartość:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" 
                   assembly="NHibernateMVC" namespace="NHibernateMVC.Models">
  <class name="Person" table="Person" dynamic-update="true" >
    <cache usage="read-write"/>
    <id name="Id" column="Id" type="int">
      <generator class="native" />
    </id>
    <property name="FirstName" />
    <property name="LastName" />
    <property name="Age" />
  </class>
</hibernate-mapping>

Po raz kolejny pamiętajcie o zwróceniu uwagi na przestrzeń nazw oraz nazwę zestawu. Powyższy plik jest klasycznym maperem. W linii 3 odwołujemy się bowiem do klasy Person, która jednocześnie jest powiązana z tabelą Person (atrybuty XML mówią w tym przypadku same za siebie). Ponadto w liniach 4-6 zwracamy uwagę na fakt, że pole Id jest generowane automatycznie.

Tutaj mała uwaga - jeśli korzystalibyście z NHibernate w innej aplikacji niż webowa, to dla każdego pliku tego typu, koniecznie należy ustawić właściwość Build Action na Embedded Resource. Podziękowania dla Jarosława Bilskiego za zwrócenie uwagi na te kwestię.

Posiadając powyższe pliki XML, możemy przystąpić do napisania prostej klasy, która będzie tworzyła obiekt sesji wykorzystywany przez NHibernate. Plik ten możecie zapisać w katalogu Models:

using NHibernate;
using NHibernate.Cfg;
using System.Web;

namespace NHibernateMVC.Models
{
    public class NHibernateSession
    {
        public static ISession OpenSession()
        {
            var configuration = new Configuration();
            var configurationPath = HttpContext.Current.Server.MapPath(@"~\hibernate.cfg.xml");
            configuration.Configure(configurationPath);
            var configurationFile = HttpContext.Current.Server.MapPath(@"~\Models\Person.hbm.xml");
            configuration.AddFile(configurationFile);
            ISessionFactory sessionFactory = configuration.BuildSessionFactory();
            return sessionFactory.OpenSession();
        }
    }
}

Krok 5 - listowanie danych

Posiadając wszystkie powyższe elementy, możemy teraz sprawdzić czy cały ten mechanizm rzeczywiście działa. Najłatwiej będzie to zrobić listując zawartość bazy danych na jednej z podstron naszej witryny.

W tym celu dodajemy nowy kontroler o nazwie HomeController, dzięki czemu nie będziemy musieli zmieniać domyślnej ścieżki routowania. Wewnątrz tworzymy (a raczej w tym przypadku wypełniamy) tylko jedną metodę dla widoku Index:

using NHibernate;
using NHibernate.Linq;
using NHibernateMVC.Models;
using System.Linq;
using System.Web.Mvc;

namespace NHibernateMVC.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            using (ISession session = NHibernateSession.OpenSession())
            {
                var persons = session.Query<Person>().ToList();
                return View(persons);
            }
        }
	}
}

W metodzie Index wykorzystujemy wcześniej utworzony obiekt sesji do odpytania bazy danych o listę osób, którą następnie przekazujemy dla widoku.

Siłą rozpędu musimy więc teraz utworzyć widok dla akcji Index (dla przypomnienia w ciele metody Index PPM pozwala na szybkie wywołania dialogu tworzenia widoku dla tej akcji). Najważniejsze jest w tym przypadku zastosowanie wzorca listy oraz wybranie naszej klasy modelu Person. Reszta opcji jest już stricte w Waszej gestii:

Jeśli wszystko zrobiliście prawidłowo, to Waszym oczom powinna się ukazać strona podobna do tej, widocznej na poniższym screenie:

Przydatne linki

Data ostatniej modyfikacji: 28.04.2014, 08:55.

Podoba Ci się ten wpis? Powiedz o tym innym!

Send to Kindle

Komentarze

blog comments powered by Disqus