Makale Özeti

NHibernate ve O/RM konusuna giriş makalesinin1 ardından NHibernate ile uygulama geliştirmeye başlıyoruz.

Makale

nh1

NHibernate - Yapılandırma ve İlk Örnek

NHibernate ve O/RM konusuna giriş makalesinin1 ardından NHibernate ile uygulama geliştirmeye başlıyoruz.

NHibernate aracı herhangi bir görsel araç içeren bir araç değil, uygulama geliştiricinin kullanacağı bir framework'tür. NHibernate ile uygulama geliştirmeye başlamak için www.nhibernate.org adresinden NHibernate'in son sürümünü indirmeniz geremektedir.

Makalemiz bir uygulama oluşturmak için adım adım ilerleyecektir, bu makalede kullanılacak örnek uygulama için aşağıdaki örnek tablo yapısının oluşturmanız gerekmektedir.

Örnek senaryo için tablo tasarımı   

CREATE TABLE [dbo].[Musteri] (
[MusteriID] [int] IDENTITY (1, 1) NOT NULL ,
[Ad] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[Soyad] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[KayitTarihi] [datetime] NOT NULL ,
[Aktif] [bit] NOT NULL
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Musteri] WITH NOCHECK ADD
CONSTRAINT [PK_Musteri] PRIMARY KEY CLUSTERED
(
[MusteriID]
) ON [PRIMARY]
GO
 

Yukarıdaki şekilde basit anlamda bir müşteri bilgilerini tutan tablo yer gözükmektedir. SQL komutlarını kullanarak aynı tabloyu kendi SQL Server sunucunuz üzerinde oluşturabilirsiniz.

NHibernate ile çalışmaya başlayalım

NHibernate ile ilgili örneğimizi gerçekleştirmek için bir Windows Application projesi açalım (proje adına NHOrnek diyorum) ve NHibernate.org adresinde indirdiğimiz NHibernate.dll dosyasını uygulamamıza referans olarak ekleyelim. Bu assembly reference olarak eklendiğinde çalışması için gerekli olan bir kaç assembly dosyasını daha uygulama klasörüne kopyalayacaktır.

Projeye Add New Item seçeneği ile yeni bir Application Configuration File (app.config) ekleyelim.

NHibernate'in proje içinde kullanılabilmesi için bazı yapılandırmaların yapılması gereklidir bunlar config dosyası aracılığı ile yapılabileceği gibi kod içerisinde de yapılabilir. Config dosyasına aşağıdaki eklentileri yaparak gerekli yapılandırmayı sağlayalım.

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

    <configSections>

        <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

    </configSections>

    <nhibernate>

        <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />

        <add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" />

        <add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />

        <add key="hibernate.connection.connection_string" value="Server=localhost;initialecatalog=OrnekDB;integrated security=true;" />

    </nhibernate>

</configuration>

Projede NHibernate'e özel bir xml elementi oluşturabilmek için configSections bölümü altında nhibernate için gerekli tanımlama yapılıyor. nhibernate elementi içinde ise uygulamanın çalışması için elzem olan tanımlamalar yanında, temel işlevler için değiştirmemize gerek olmayan ancak nhibernate'in genişletilebilir yapısı için gerekli tanımlamalar yapılıyor. Örneğin hibernate.connection.provider elementine verilen değeri nhibernate için sunulan arayüzleri kullanarak kendi connection provider'ınzı yazmadığını sürece değiştirmenize gerek yoktur.

hibernate.dialect değeri ile bağlanılacak olan veritabanına göre belirlenir. Burada SQL Server'a bağlanılacağı için MsSql2000Dialect değeri verilmiştir. Bu sayede NHibernate'in otomatik oluşturacağı SQL sorgularında veritabanı sunucumuzun anlamayacağı sorgular oluşmamasını sağlar.

 

Veritabanı Yönetim Sistemi Dialect
DB2 NHibernate.Dialect.DB2Dialect
PostgreSQL NHibernate.Dialect.PostgreSQLDialect
MySQL NHibernate.Dialect.MySQLDialect
Oracle (any version) NHibernate.Dialect.OracleDialect
Oracle 9/10g NHibernate.Dialect.Oracle9Dialect
Sybase NHibernate.Dialect.SybaseDialect
Microsoft SQL Server 2000 NHibernate.Dialect.MsSql2000Dialect
Microsoft SQL Server 7 NHibernate.Dialect.MsSql7Dialect
Firebird NHibernate.Dialect.FirebirdDialect

Yukarıda hangi veritabanı yönetim sistemi için hangi dialect değerinin kullanılması gerektiğini belirten ve NHibernate dokumantasyonundan alınmış bir tablo gözükmektedir.

driver_class ise kullanılacak ADO.NET providerı için uygun nesneleri sağlayan NHibernate assembly'si içinde yer alan IDriver arayüzünü uygulayan bir sınıf olmalıdır. SqlClientDriver değeri Sql Server için kullanılmaktadır. Diğer veritabanı sistemleri için kullanılabilecek değerler aşağıdaki grafikde gözükmektedir.

connection_string değeri ise bağlantı için gerekli olan connectionstring değerinin tanımlandığı xml elementidir.

XML Mapping

NHibernate veritabanındaki tablolar ile uygulamada yer alan sınıflar arasındaki mapping işlemi için xml formatında bir deklarasyona ihtiyac duyar. Bu dosyalar hbm.xml  uzantısı ile biten ve uygulama içine gömülü olarak dağıtılan dosyalardır.

XML mapping işlemine gelmeden önce aşağıdaki Musteri sınıfını oluşturup uygulamıza ekleyelim.

using System;

namespace NHOrnek

{

    public class Musteri

    {

        private int _MusteriID;

        private string _Ad;

        private string _Soyad;

        private DateTime _KayitTarihi;

        private bool _Aktif;

 

        public int MusteriID

        {

            get { return _MusteriID; }

            set { _MusteriID = value; }

        }

        public string Ad

        {

            get { return _Ad; }

            set { _Ad = value; }

        }

        public string Soyad

        {

            get { return _Soyad; }

            set { _Soyad = value; }

        }

        public DateTime KayitTarihi

        {

            get { return _KayitTarihi; }

            set { _KayitTarihi = value; }

        }

        public bool Aktif

        {

            get { return _Aktif; }

            set { _Aktif = value; }

        }

        public override string ToString()

        {

            return this.Ad + " " + this.Soyad + "\n" + this.Aktif.ToString() + "\n" + this.KayitTarihi.ToShortDateString();

        }

 

    }

}

Yukarıdaki class tanımlaması ile daha önce oluşturduğumuz tablo arasındaki ilişki dikkatinizi çekmiş olmalı. Burada oluşturulan Musteri sınıfı daha önce oluşturduğumuz musteri tablosunda yer alan dataların uygulamadaki temsili için kullanılacaktır.

NHibernate'in verileri bu sınıf ve tablo arasında aktarabilmesi için uygulama geliştiricinin mapping işlemini yerine getirmesi gerekmektedir. Bu işlemi hbm.xml dosyasını oluşturarak yapabiliriz. Projeye Add New Item seçeneği ile yeni bir Xml dosyası ekleyelim ve adını NHOrnek.hbm.xml olarak belirleyelim.

Oluşturulan xml dosyası projede yer alan her tablo ve sınıf maplemesi için bir tane olacağı gibi, her mapping için ayrı ayrı dosya eklenebilmektedir. Bu örnekde zaten bir map işlemi yapılacağı için zaten tek dosya olacak. Dosya isimlerindeki hbm.xml dışındaki bölüm çalışmayı etkileyecek değerler değildir, yani burada proje ismi ile dosya isminin aynı olması zorunluluk değildir.

<?xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">

    <class name="NHOrnek.Musteri, NHOrnek" table="Musteri">

        <id name="MusteriID" column="MusteriID" type="Int32" unsaved-value="0">

            <generator class="identity" />

        </id>

        <property name="Ad" column="Ad" type="String" length="50" />

        <property name="Soyad" column="Soyad" type="String" length="50" />

        <property name="KayitTarihi" column="KayitTarihi" type="DateTime" />

        <property name="Aktif" column="Aktif" type="Boolean" />

    </class>

</hibernate-mapping>

Yukarıdaki xml kodunu NHOrnek.hbm.xml içine yazınız.

NHibernate mapping dosyası içinde root element hibernate-mapping olmalıdır. Her tablo/class mapping tanımlaması için bir <class> elementi oluşturulmalıdır.

<class> elementi name özelliği Namespaceismi.Classismi, Assemblyismi şeklindedir.

<class> elementi table özelliği veritabanı tarafındaki tablonun ismidir. Varsayılan değer name özelliğinde belirlenmiş olan class ismi olduğu için tablo ismi ve class ismi aynı olduğu durumlarda bu özelliğe değer atanması zorunluluk değildir.

<class> elementi içinde <id> elementi oluşturularak tablodaki birincil anahtar alanı ve bu alanın sınıfımızda karşılık geldiği property tanımlanır.

<id> elementi name özelliği sınıfdaki propertynin adını belirler.

<id> elementi column özelliği tablodaki sütunun ismini belirler, eğer property ismi ile tablodaki sütun ismi aynı ise bu alanın kullanıması zorunluluğu yoktur.

<id> elementi type özelliği bu property nin türünü belirler.

<id> elemti unsaved-value özelliği ise bu property nin yeni oluşturulmuş bir nesnedeki değerinin ne olduğunu belirler. Örneğin sınıftaki property Int32 olduğunda bunun varsayılan değeri 0'dır ve bu özellikte bu şekilde tanımlanır. NHiberate bu değeri daha sonra bir nesneyi yeni kayıt olarak mı yoksa güncelleme olarak mı kaydedeceğini belirlerken kullanır. (daha sonra bahsedilecek olan SaveOrUpdate metodunda)

<generator> elementi birincil anahtarının türüne göre farklı class deklarasyonu yada tanımlaması değerini alır. Buradaki identity değeri veritabanında otomatik artan sayı olarak tanımlanmış olan bir sütun için kullanmıştr. Diğer ihtimaller bu değerin yeni kayıt girilirken belirlenmesi gibi durumlarda kullanılabilir. Ayrıntılı bilgi için nhibernate ve hibernate dokumanlarına basvurulabilir. NHibernate'in genisleyebilir yapısı sayesinde kendi generator class'ınızı oluşturabilirsiniz.

<property> elementi sınıf içinde tanımlanan bir property ve bunun tabloda karşılık geldiği sütunu belirler.

<property> elementi name özelliği sınıftaki property'nin ismini belirler.

<property> elementi column özelliği veritabanındaki sütun ismini belirler. Bu özellik sütun ismi ve property ismi aynı olduğu takdirde kullanılmayabilir.

<property> elementi length özelliği zorunlu olmayan ancak veri türüne göre kullanılması gereken propertylerde kullanılır. Örneğin Ad ve Soyad sütunları veritabanında 50 karakter uzunluğunda tanımlandığı için burada da propertylerin uzunluğu 50 olarak belirlenmiştir.

NHibernate'in tüm elementleri ve özelliklerini görebilmek için hbm.xml dosyasını doğrulayan ve nhibernate zip dosyası içinde yer alan nhibernate-configuration-2.0.xsd dosyasını kullanabilir ve xml dokumanınız doğrulamak için kullanabilirsiniz.

Tanımlama dosyasının projeye dahil edilmesi

Oluşturulan hbm.xml dosyası uygulama gömülü olarak dağıtmak için bu dosya projeye embedded resource olarak eklemelidir. Bunun  için Solution Explorer'dan hbm.xml dosyasının seçilir ve View>Properties menüsünden Properties penceresi açılır. Dosyanın özelliklerinin gösterildiği bu ekranda dosyanın Build Action özelliği Embedded Resource olarak belirlenmelidir.

Bu işlemi gerçekleştirdikten sonra projede bulunan Form1 formunu aşağıdaki şekilde tasarlayın ve butonun click olayına aşağıdaki kodu yazın.

 

    private void button1_Click(object sender, System.EventArgs e)

    {

        NHibernate.Cfg.Configuration cf=new NHibernate.Cfg.Configuration();

        cf.AddAssembly(this.GetType().Assembly);

        NHibernate.ISessionFactory f=cf.BuildSessionFactory();

        NHibernate.ISession s=f.OpenSession();

        Musteri m;

        m=s.Get(typeof(Musteri),int.Parse(textBox1.Text)) as Musteri;

        s.Close();

        if (m==null)

        {

            MessageBox.Show("Müşteri bulunamadı.");

        }

        else

        {

            MessageBox.Show(m.ToString());

        }

 

    }

Uygulamayı ilk çalıştırdığınız da sonuç olarak müşteri bulunamadı diyecektir. Daha sonra oluşturduğunuz veritabanı içindeki Musteri tablosuna aşağıdaki gibi örnek bir kayıt girip test ettiğinizde aşağıdaki sonucu alırsınız.

 

Bu örneğimizde kullandığımız ve sonraki NHibernate makalelerimizde yer alan örneklerde kullanmaya devam edeceğimiz NHibernate nesne modelinden ilerleyen makalelerde bahsetmeye devam edeceğiz.

 

Cengiz HAN
Microsoft ASP.NET MVP
cengiz@cengizhan.com

 

1Object/Relational Mapping ve NHibernate başlıklı makaleme yine yazgelistir.com üzerinden erişebilirsiniz.