Makale Özeti

Fluent NHibernate'in asp.net projelerinde kullanımına yönelik yaklaşımı konu alan içerik.

Makale

Merhabalar, bu yazıda asp.net ile birlikte NHibernate'in etkili bir şekilde kullanımına değiniyor olacağım. NHibernate'in sağladığı özelliklerden faydalanarak performanslı bir uygulama geliştirmemiz gerekiyor. Bu yazı klasik kullanımdan ziyade veri tabanı bağlantısının önemiyle alakalı bilgiler içeriyor.

NHibernate de Session kavramı önemli bir yer tutuyor. Veritabanı ile konuşma işlemleri için Session nesnesi kullanıyor. Bu nesne asp.net de bulunan Session nesnesi ile aynı isimdedir. İki nesneyi birbirine karıştırmamak gerekekir. NHibernate database ile konuşurken Session nesnesinin OpenSession() ile açıklması gerekiyor. Arkaplanda veritabanı ile alakalı bağlantı kuruluyor ve istediğimiz işlemleri(ekle, sil gibi) gerçekleştirmemize olanak sağlıyor.

ASP.NET ile ado.net yapısı için bağlantı yönetimine dayalı farklı bir çok yaklaşım vardır. Klasik yöntem her bir sorgu için bağlantının açılıp kapanmasına dayalıdır. Bu yazıda anlatacağım durum ise NHibernate'in OpenSession() yordamını sayfanın çağırıldığı andan tamamlanana kadar Session nesnesinin açık kalmasına dayalıdır. Bu yapıya göre istemci herhangi bir asp.net sayfasını çağırdığında veritabanı için oturum oluşturulur. Sayfa içindeki tüm db işlemleri bu oturum ile(yeni bir oturum oluşturmadan) gerçekleştirilir. Ve oturum sonlandırılır.

Gelelim kodlama mevzusuna; Öncelikle Nhibernate'i configure edelim. Aşağıdaki xml dosyası ve kod bloğunu kullanalım.

Xml dosyası:

<?xml version="1.0" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2" >
  <session-factory>
    <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
    <property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
    <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
    <property name="connection.connection_string">server=.;database=ulak;integrated security=true;</property>
    <property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
    <property name="current_session_context_class">web</property>
  </session-factory>
</hibernate-configuration>

 

Kod bloğu:

var configPath = PathHelper.GetAbsolutePath("~/App_Data/Configuration/FluentNHibernate/DatabaseConfiguration.xml");
var mappingFilePath = PathHelper.GetAbsolutePath("~/bin/OMR.Ulak.Entities.Maps.NHibernate.dll");

var cfg = new Configuration().Configure(configPath);

SessionFactory = Fluently.Configure(cfg)
    .Mappings(m =>
    m.FluentMappings.AddFromAssembly(Assembly.LoadFile(mappingFilePath))
    )
    .ExposeConfiguration(FNHBBuildSchema) // FNHBBuildSchema delege metodu. İlerleryen kısımlarda açıklanmıştır.
    .BuildSessionFactory();

 

 

Konfigrasyon işlemi bu şekilde hallolduğuna göre geriye SessionFactory sınıfından OpenSession yordamı ile Session nesnesini almak kalıyor. İşte bu noktada bu yazıdaki yaklaşımı göz önüne alıp, sayfa olayları ile Session nesnesini her sayfa yenilemesi için bir kere oluşturmalıyız.


Öncelikle global.asax dosyasında aşağıdaki gibi bir tanımlama yapılmalıdır. Uygulama çağırıldığında SessionFactory nesnesinin bir örneği oluşturulur:

 

public static ISessionFactory SessionFactory { get; private set; }
internal static object _lockObject = new object();

protected void Application_Start(object sender, EventArgs e)
{
    lock (_lockObject)
    {
        if (SessionFactory == null)
        {
            lock (_lockObject)
            {
                var configPath = PathHelper.GetAbsolutePath("~/App_Data/Configuration/FluentNHibernate/DatabaseConfiguration.xml");
                var mappingFilePath = PathHelper.GetAbsolutePath("~/bin/OMR.Ulak.Entities.Maps.NHibernate.dll");

                var cfg = new Configuration().Configure(configPath);

                SessionFactory = Fluently.Configure(cfg)
                    .Mappings(m =>
                    m.FluentMappings.AddFromAssembly(Assembly.LoadFile(mappingFilePath))
                    )
                    .ExposeConfiguration(FNHBBuildSchema)
                    .BuildSessionFactory();
            }
        }
    }
}

private static void FNHBBuildSchema(Configuration config)
{
    new SchemaExport(config).Create(false, true); // Map edilen sınıfların şemasal manada veritabanında oluşturulmasını sağlar.
}

 

 

Herhangi bir sayfa çağırıldığında sayfa ile ilgili olayları denetleyebilmek için de basit bir HttpModule geliştirelim:

 

namespace OMR.Ulak.Data.Web
{
    using System.Web;
    using NHibernate;
    using System;
    using NHibernate.Context;

    public class SessionModule : IHttpModule
    {
        public static ISessionFactory SessionFactory { get; private set; }

        public void Dispose()
        {
            if (SessionFactory != null)
                SessionFactory.Dispose();
        }

        public void Init(HttpApplication context)
        {
            if (context == null)
                throw new ArgumentException("context");

            context.BeginRequest += new EventHandler(context_BeginRequest);
            context.EndRequest += new EventHandler(context_EndRequest);
        }

        void context_BeginRequest(object sender, EventArgs e)
        {
            if (!CurrentSessionContext.HasBind(UlakDataHttpApplication.SessionFactory))
            {
                var session = UlakDataHttpApplication.SessionFactory.OpenSession();
                CurrentSessionContext.Bind(session);
            }
        }

        void context_EndRequest(object sender, EventArgs e)
        {
            if (CurrentSessionContext.HasBind(UlakDataHttpApplication.SessionFactory))
                CurrentSessionContext.Unbind(UlakDataHttpApplication.SessionFactory);
        }
    }
}

 


Webconfig dosyasına bu modülü tanımlayalım:

 

    <httpModules>
      <add name="NHibernateSessionModule" type="OMR.Ulak.Data.Web.SessionModule"/>
    </httpModules>

 

Gerekli tanımlamaları gerçekleştirdikten sonra sayfa içerisinde aşağıdaki gibi kullanıma -umarım- hazır haldedir

 

using System;
using OMR.Ulak.Entities.Common;

namespace OMR.Ulak.WebApp
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Sayfa oluşturulduğuda SessionFactory nesnesine atama yapılmıştı.
            // Şuanki aktif session nesnesini getir.
            using (var session = Global.SessionFactory.GetCurrentSession())
            {
                using (var tran = session.BeginTransaction())
                {
                    // Setting nesnesinin örneği oluşturulur.
                    var setting = new Setting()
                    {
                        Name = "stx",
                        Value = "vallue",
                        Description = "deskrpşın"
                    };

                    // Aktif oturum nesnesi ile kaydetme işlemini gerçekleştir.
                    session.Save(setting);

                    tran.Commit();
                }
            }

        }
    }
}

 

 

Faydalı olması dileğiyle.