msHOWTO

12 Şubat 2015 Perşembe

NHiberNate ile EmptyInterceptor ve IInterceptor Kullanarak Loglama Nasıl Yapılır ?

Merhabalar değerli okurlar, 
Bugün sizlere NHibernate kullanarak Logging işlemini nasıl yapılabileceğini anlatacağım. Senaryomuzdan hemen bahsetmek istiyorum. Var olan herhangi bir database içerisinde dilediğimiz bir tablo üzerinde yapılan işlemi ve işlemdeki verileri loglamak istediğimizi düşünelim. Alacağımız log bilgilerinde hangi kullanıcının hangi tablo içindeki hangi veri üzerinde hangi işlemi yaptını ve işlem sonucundaki verinin kaydını tuttuğumuzu düşünelim. Oluşturduğumuz senaryo loglama sistemi için şuan yeterli görünmekte. Dilerseniz siz log kayıt bilgilerine istediğiniz bilgiyi ekleyebilirsiniz. 
İlk olarak eğer yapılan işlemi database üzerine yansıtılmadan yakalamak ve ona göre işlem yapmak istiyorsak , ki senaryomuz gereği bunu yapmamız gerekir. Çünkü yapılan işlemi application katmanında her işlemde parametre olarak almaktansa bu şekilde işlem database üzerine yansıtılmadan araya girip yapılan işlemi ve veriyi yakalamak çok daha mantıklı ve profesyonelce durmaktadır. 
Eğer orm olarak NHibernate kullanıyorsak ve yukarıda tanımladığım işlemi yapmak istiyorsak, NHibernate içerisinde bulunan IInterceptor inteface ini incelemek ve bu interface i kendine implemente etmiş olan EmptyInterceptor class ını iyi anlamamız gerekmektedir. IInterceptor interface i içerisindeki methodları incelecek olursak , 

void AfterTransactionBegin(ITransaction tx); // Kullanılan session içerisindeki transaction başladıktan sonra tetiklenen method
void AfterTransactionCompletion(ITransaction tx); // Kullanılan session içerisindeki transaction tamamlandıktan sonra tetiklenen method
void BeforeTransactionCompletion(ITransaction tx); //Kullanılan session içerisindeki transaction tamamlanmadan önce tetiklenen method

....
....
....

Methodların isimlerinden ne zaman tetiklendiği zaten belli olmaktadır. Bizim senaryomuz gereği kullanacağımız methodlar ise ;

void OnDelete(object entity, object id, object[] state, string[] propertyNames, IType[] types); // Entity nin silinmeden önce tetiklenen method
bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, IType[] types); // Entity nin güncellenmeden önce tetiklenen method
bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types); // Entity nin eklenmeden önce tetiklenen method

EmptyInterceptor class'ına bakacak olursak, IInterceptor interface ini implemente ettiğini ve bu interface içerisindeki methodları virtual olarak hazırladığını görmekteyiz. Bu şu anlama gelmektedir. Eğer ben bu class üzerinden miras alarak kendi class'ımı oluşturursam, OOP mantığı ile hem IInterceptor interface indeki tüm methodları yapabilir hale gelmiş oluyorum, hem de minimum istekleri karşılayıp sadece kendi özel olarak kodlamak istediğim methodları ezerek, yapmak istediğim işleri yapabilir hale geliyorum. OOP'ın bu güzel nimetlerini kullanarak kendi Interceptor class'ımı oluşturup onu adeta bir log class'ı haline sokabilirim. Aynen şu şekilde , 

[Serializable]
public class MyInterceptor : EmptyInterceptor
{
public string _databaseName = "";
public string _kullaniciAdi = "";
public string _sifre = "";
public MyInterceptor(string databaseName,string kullaniciAdi,string sifre)
{
_databaseName = databaseName;
_kullaniciAdi = kullaniciAdi;
_sifre = sifre;
}
public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types)
{
//  yapılan işlem insert işlemidir ve insert yapılan nesne, property isimleri, tipleri gelmektedir. Bu bilgilerden faydalanarak şu tablo üzerinde şu veri üzerinde şu işlem yapıldı. diyebiliyoruz. Constructure methodunda da kullanıcı adı ve şifre bilgisini alıyorum. İsterseniz sadece kullanıcı bilgisini alabilirsiniz. Tamamen size kalmış bir durum. Tüm bilgileri aldıktan sonra loglama işlemini dilediğimiz gibi yapabiliriz. 

return true;

}

public override void OnDelete(object entity, object id, object[] state, string[] propertyNames, IType[] types)
{
//  yapılan işlem delete işlemidir ve delete yapılan nesne, property isimleri, tipleri gelmektedir. Bu bilgilerden faydalanarak şu tablo üzerinde şu veri üzerinde şu işlem yapıldı. diyebiliyoruz. Constructure methodunda da kullanıcı adı ve şifre bilgisini alıyorum. İsterseniz sadece kullanıcı bilgisini alabilirsiniz. Tamamen size kalmış bir durum. Tüm bilgileri aldıktan sonra loglama işlemini dilediğimiz gibi yapabiliriz.
}
public override bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, IType[] types)
{
//  yapılan işlem update işlemidir ve update yapılan nesnenin güncellenmek istenen değerleri ve veri tabanında kayıtlı olan değerleri, property isimleri, tipleri gelmektedir. Bu bilgilerden faydalanarak şu tablo üzerinde şu veri üzerinde şu işlem yapıldı. diyebiliyoruz. Constructure methodunda da kullanıcı adı ve şifre bilgisini alıyorum. İsterseniz sadece kullanıcı bilgisini alabilirsiniz. Tamamen size kalmış bir durum. Tüm bilgileri aldıktan sonra loglama işlemini dilediğimiz gibi yapabiliriz.
return true;
}

}

Evet değerli okurlar, artık Interceptor class'ımız hazır. Tek yapmamız gereken Interceptor class'ımızı session üzerinde tutturmak ve configuration bilgilerine eklemek. Bunun için aşağıdaki kodları yazmamız yeterli olacaktır. 

Configuration cfg = new Configuration();
public MyInterceptor ins = new MyInterceptor ("myLogDatabaseName");
cfg.SetInterceptor(ins);
ISessionFactory factory ;
ISession session;
factory = cfg.BuildSessionFactory();
session = factory.OpenSession(ins);

kodlar yeterli olacaktır. Umarım faydalı olmuştur değerli okurlar.

Bir sonraki makalemde görüşmek üzere. 

Koray Düzgün. MCTS