Makale Özeti

Bu makalede veritabanında yapılan işlemler için kayıtların(loglama) tutulması için gerekli olan Log katmanın beraber oluşturacağız. Veritabanın loglama özelliklerinden farklı olarak programsal olarak bu katmanı oluşturacağız.

Makale

Veritabanı İşlemleri Üzerinde Log(Kayıt) Katmanı Oluşturma

Bu makalede veritabanında yapılan işlemler için kayıtların(loglama) tutulması için gerekli olan Log katmanın beraber oluşturacağız. Veritabanın loglama özelliklerinden farklı olarak programsal olarak bu katmanı oluşturacağız.

Veri tabanı düzenli bilgiler topluluğudur. Bilgisayar terminolojisinde veritabanı, sistematik erişim imkanı olan, yönetilebilir, güncellenebilir , taşınabilir, birbirleri arasında tanımlı ilişkiler bulunabilen bilgiler kümesidir. Ürün haline gelen bir veritabanında hangi tabloların üzerinde hangi kullanıcılar tarafından hangi işlemlerin yapıldığı(update,insert,delete) bilgisini tutmak çok önemlidir. Kullanıcıya sunulan verinin her zaman doğru bilgi olması gerekmektedir. Veri üzerinde oluşan bir hata ciddi hasarlara yol açabilir. Hatanın bulunup verinin doğru değerlere geri döndürülmesi ya da hatanın nasıl gerçekleştiğinin bulunması gerekebilir. Bazı durumlarda hatayı meydana getiren kişinin kimliğini bile elde edebilmek çok önemli olabilmekter Bir kayıt belli bir duruma gelene kadar hangi aşamalardan nasıl geçtiği bilgisi belirli kritik tablolarda erişilmesi gereken bir bilgidir. Bu loglama programı kısmende olsa performans kısıtı getirse bile önemli olan tablolarda bu işlemi yapmak gerekmektedir. Loglama yapmanın birden çok yöntemi vardır. Bu makalede loglamayı bir programcı olarak yine bir veritabanı tabloları kullanarak bir yapı oluşturup bu yapı üzerinde tutacağız. Aşağıdaki tabloları oluşturup aşağıdaki tablolar üzerinde loglama yapacağız. Bu loglama yaptığımız tablolar aynı veritabanında tutulabileceği gibi farklı bir ortamda da tutulabilir. Farklı bir ortamda tutulursa veritabanı dosyaları ya da veritabanı sunucusu üzerinde gelebilecek aksaklıklarda log kayıtlarımız etkilenmeyecektir. Yapı için gerekli olan tablolar ve sp ler aşağıdadır.

USE [Loglama]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Tablo](
[TabloId] [int] IDENTITY(1,1) NOT NULL,
[TabloAd] [nvarchar](200) COLLATE Turkish_CI_AS NULL,
[AktifMi] [bit] NULL DEFAULT ((1)),
PRIMARY KEY CLUSTERED
(
[TabloId] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
 

Tablo tablomuz veritabanında log kayıtlarını tutulmasını istediğimiz tablo isimlerini tutacaktır.

USE [Loglama]
GO
/****** Object: Table [dbo].[LogDurum] Script Date: 01/15/2008 22:15:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[LogDurum](
[LogDurumId] [int] IDENTITY(1,1) NOT NULL,
[LogDurumAd] [nvarchar](200) COLLATE Turkish_CI_AS NULL,
[AktifMi] [bit] NULL DEFAULT ((1)),
PRIMARY KEY CLUSTERED
(
[LogDurumId] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
 

LogDurum tablosu 3 satir ihtiva eder. Bunlar update, delete ve insert satırlarıdır.LogDurum tablosu tablo üzerinde nasıl bir işlem gerçekleştiği bilgisini tutulacaktır.(insert.update,delete)

USE [Loglama]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[TabloLog](
[TabloLogId] [int] IDENTITY(1,1) NOT NULL,
[TabloId] [int] NULL,
[PrimaryKey] [int] NULL,
[Parametre] [nvarchar](max) COLLATE Turkish_CI_AS NULL,
[LogTarih] [datetime] NULL,
[UserId] [int] NULL,
[LogDurumId] [int] NULL,
PRIMARY KEY CLUSTERED
(
[TabloLogId] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

GO
USE [SetTakip]
GO
ALTER TABLE [dbo].[TabloLog] WITH CHECK ADD FOREIGN KEY([LogDurumId])
REFERENCES [dbo].[LogDurum] ([LogDurumId])
GO
ALTER TABLE [dbo].[TabloLog] WITH CHECK ADD FOREIGN KEY([TabloId])
REFERENCES [dbo].[Tablo] ([TabloId])
GO
ALTER TABLE [dbo].[TabloLog] WITH CHECK ADD FOREIGN KEY([UserId])
REFERENCES [dbo].[User] ([Id])

TabloLog tablomuz log yapacağımız verileri tutacaktır. Veritabanında ilgili tablolarda her yapılan işlemi kim tarafından ne zaman nasıl bir değişiklik olarak yapıldığı bilgisini tutar. TabloLogId sütünu ile identity primary key oluşturulmuştur TabloId sütunu ile hangi tablonun log kayıtının tutulduğu bilgisi tutulmaktadır. TabloId Tablo tablomuzu referans etmektedir. PrimaryKey alanı ile loglama yapılan tablonun hangi satırının loglama yapıldığı bilgisi tutulmuştur. Bu bilgi aslında Parametre alanında log olarak tutulmaktadır fakat performans olarak hızlı raporlar alınabilmesi için ayrı bir sütun olarak belirtilmiştir.Parametre alanında daha sonra belirteceğim gibi loglama yapılan kayıt tutulacaktır. Bu kayıt XML string olarak tutulacaktır. Nasıl tabloda ilgili verinin xml e çevrileceğini daha sonra programatik olarak göstereceğim. UserId sütunu ile bu veri üzerinde işlem yapan kişinin tutulmaktadır. LogDurumId sütünunda ise LogDurum tablosu referans edilmektedir. LogDurum tablosu tablo üzerinde nasıl bir işlem gerçekleştiği bilgisini tutar.(insert.update,delete). Bu tablolardan hariç olarak User tablomuz olacaktır. Bu tabloda ise sisteme giren kullanıcı bilgileri tutulacaktır.

 

TabloLog tablosuna devamlı olarak insert yapılacaktır, kayıtlar üzerinde herhangi bir güncelleme ya da silme işlemi olmayacaktır. Bunun için TabloLog tablosunun büyüklüğü devamlı olarak artacaktır. TabloLog tablosunun kayıtları çok büyük olabileceği için sık sık kontrol edilmeli performans sıkıntısı çekilirse de partition table yapılabilir ya da eski kayıtlar başka yerlere aktarılabilir. TabloLog tablosuna ekleme yapmak için aşağıdaki stored procedure kullanılacaktır.

set ANSI_NULLS ON

set QUOTED_IDENTIFIER ON

go

CREATE PROC [dbo].[InsertTabloLog]

(@pTabloId int,

@pPrimaryKey int,

@pParametre nvarchar(max),

@pLogTarih datetime,

@pUserId int,

@pLogDurumId int,

@pTabloLogId int output)

AS

            INSERT INTO

                        TabloLog(TabloId,PrimaryKey,Parametre,LogTarih,UserId,LogDurumId)

            VALUES(@pTabloId,@pPrimaryKey,@pParametre,@pLogTarih,@pUserId,@pLogDurumId)

SET @pTabloLogId = @@IDENTITY

 

Kod tarafında loglama için aşağıdaki yapı uygulanmalıdır. Log kayıdı tutulacak tablonun entity katmanı insert,update ya da delete için doldurulduktan sonra bu entity aşağıdaki kod ile xml kayıdına çevirilmelidir. Bu xml kaydı TabloLog tablomuzun Parametre alanını dolduracaktır. Dolu olan entity GetXmlString fonksiyonuna gönderildiğinde bu entity ve içerisindeki değerler xml stringine dönüşür.

public static string GetXmlString(object k)

{

    XmlSerializer objXmlSerializer = new XmlSerializer(k.GetType());

    TextWriter TW = new StringWriter();

    objXmlSerializer.Serialize(TW, k);

    return TW.ToString();

}

Örnek olarak aşağıdaki gibi bir entity bu fonksiyona girince aşağıdaki xml stringi haline gelmektedir.

using System;
using System.Collections.Generic;
using System.Text;
namespace EntityLayer
{
    public partial class entBolge
   
{
        private int _BolgeId;
        private string _BolgeAd;
        private
bool? _AktifMi;
       
public int BolgeId
        {
        get
        {
return _BolgeId; }
        set
        { _BolgeId =
value; }
    }
    public string BolgeAd
    {
        get
            {
return _BolgeAd; }
        set
            { _BolgeAd =
value; }
    }
    public bool? AktifMi
    {
    get
        {
return _AktifMi; }
    set
        { _AktifMi =
value; }
    }
    }
    public entBolge(int parBolgeId, string parBolgeAd, bool? parAktifMi)
    {
        this._BolgeId = parBolgeId;
        this._BolgeAd = parBolgeAd;
        this._AktifMi = parAktifMi;
    }
   
}
}

<?xml version="1.0" encoding="utf-16"?>
<entBolge xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<BolgeId>127</BolgeId>
<BolgeAd>İç Anadolu Bölgesi</BolgeAd>
<AktifMi xsi:nil="true" />
</entBolge>

Data katmanımızda yukarıdaki gibi bir entity'nin eklenmesi durumunda TabLog tablomuz aşağıdaki gibi dolmalıdır.

 

public void InsertTabloLog(entTabloLog parEntTabloLog, DbConnector parDbConnector)

{

    DbParamCollection insDbParamCollection = new DbParamCollection();

    insDbParamCollection.Add("@pTabloId",parEntTabloLog.TabloId);

    insDbParamCollection.Add("@pPrimaryKey",parEntTabloLog.PrimaryKey);

    insDbParamCollection.Add("@pParametre",parEntTabloLog.Parametre);

    insDbParamCollection.Add("@pLogTarih",parEntTabloLog.LogTarih);

    insDbParamCollection.Add("@pUserId",parEntTabloLog.UserId);

    insDbParamCollection.Add("@pLogDurumId",parEntTabloLog.LogDurumId);

    insDbParamCollection.AddOutput("@pTabloLogId",DbType.Int32);

    parDbConnector.ExecuteNonQuery("InsertTabloLog",insDbParamCollection);

    parEntTabloLog.TabloLogId = Convert.ToInt32(insDbParamCollection.GetOutPutParameter().Value);

}

TabloId= 18 ---> Tablo tablosunda Bolge tablosunun id'si

PrimaryKey=127 --->Bolge tablosunda eklenen kaydın id'si

LogTarih= Logun atıldığı tarih '15.01.2007 02:14:21'

UserId --->User tablosunda kaydı ekleyen kişinin id'si

LogDurumId --> LogDurum tablosunda insert satırının id'si değerlerini alacaktır

 

Yukarıdaki yapı veritabanı üzerinde karmaşık log kayıtları tutma yöntemlerinden kurtulup basit bir log kayıt altyapısı sunmaktadır. Yapacağınız tüm yapılara bu mimariyi ekleyebilir ve kullanabilirsiniz.

Makale ya da kodlarda bulunan hatalar ya da sorularınız için mehmetaliecer@gmail.com adresinden bana ulaşabilirsiniz. İyi çalışmalar.

Mehmet Ali ECER

www.mehmetaliecer.com