ADO.NET Transaction İşlemi – I

DbTransaction nesnesi, veritabanı sistemine gönderdiğimiz sorguya ait transaction yönetimini sağlamak için kullanılır. Bilindiği gibi transaction(işlem) kavramı, veritabanı yönetim sistemlerinde önemli bir yere sahip olup birbirleriyle ilişkili iş parçacıklarının bulunduğu mantıksal bir birim olarak düşünebilir. Transaction yönetimi, aynı iş parçacığında seri bir şekilde yürütülecek sorguların hatasız bir şekilde sonuçlanıp sonuçlanmadığının kontrolünü sağlar. Klasik bir örnek olarak banka sisteminde havale uygulamasını ele aldığımızda ilk önce havaleyi yapan kişinin hesabından ilgili miktar düşürülür ve havale yapılan kişinin hesabına o kadar miktar eklenir. Dışarıdan basit görünen bu sürecin herhangi bir halkasında meydana gelecek bir hata kaynak veya hedef siteminde bilgi tutarsızlığına neden olacaktır. Bu yüzden bu işlemlerin transaction yönetiminde gerçekleştirilmesi gerekir. “Ya hep ya hiç” mantığıyla çalışan transaction işleminin esas amacı “veri bütünlüğü” olup, süreç içerisinde istenmeyen bir durum olduğu zaman önceki iş parçacıklarının geri alınmasıdır. Yani süreç, başlangıç noktasına geri döndürülür ve süreç içindeki hiçbir iş parçacığının gerçekleşmemiş olduğu kabul edilir. Büyük ölçekli VTYS’lerde dahili transaction yönetimi bulunmaktadır. Örneğin SQL Server’da çalıştırdığımız bir UPDATE veya DELETE işlemi esnasında herhangi bir kesinti olduğu zaman o zamana kadar gerçekleştirilmiş güncelleme veya silme işlemleri geri alınır ve veriler eski haline geri dönmüş olur. Bu geri alma işlemine ROLLBACK(geri sarmak), işlemler hatasız çalıştığı durumda değişikliklerin kalıcı hale getirilmesine COMMIT(işlemek) denilir.
ADO.NET’te transaction yönetimini sağlayan temel class, System.Data.Common.DbTransaction sınıfıdır. ADO.NET 2.0’dan önceki sürümlerde bu class temel alınarak provider’lara bağlı transaction sınıfları oluşturulmuştur(SqlTransaction, OleDbTransaction .). ADO.NET 2.0 ile birlikte transaction yönetimi, provider’lardan bağımsız da yapılabilir hale getirildi ve bu amaçla System.Transactions.dll kütüphanesi geliştirildi. Önce provider’lara bağımlı yapı üzerinde çalışacağız. DbTransaction sınıfının üyelerini listeleyelim;
Connection: Transaction nesnesinin ilişkili olduğu Connection nesnesini belirtir.
Commit(): Transaction sürecinin başarı olması durumunda verileri, database üzerinde kalıcı kılar.
IsolationLevel: Transaction’ların birbirileriyle olan izolasyon seviyesini belirtir (ReadUncommitted, ReadCommitted, RepeatableRead .).
Rollback(): Hatalı iş parçacığına kadar yapılmış işlemleri geri sarıp, süreci işlenmemiş kılar.
Sorgularımızı transaction yönetiminde gerçekleştirmek için öncelikle Connection ve Command nesnesi tanımlanır. Bu nesnelerin ilgili parametreleri set edilir. Verikaynağıyla bağlantı kurmak amacıyla Connection nesnesi Open() yapılır. Ardından Connection nesnesinin BeginTransaction() metodu kullanılarak bir Transaction nesnesi oluşturulur. Bu nesne, Command nesnesiyle ilişkilendirilir. Sorgumuzun başarılı olup olmadığını yakalamak için try-catch bloğu kullanılır. Eğer sorgu başarılı olursa yani try bloğu tümüyle işlendiği zaman Transaction nesnesi Commit() edilir. Sorgunun başarısız olma durumunda yani program catch bloğuna girerse Transaction nesnesi Rollback() edilir. Aşağıdaki tabloda basit bir transaction yönetimini bulabilirsiniz.

Dim oCnn As New SqlConnection(CnnStr)
Dim sQry As String = "UPDATE Musteri SET AdSoyad='Ayşe Güler' WHERE MusteriId=3;"
Dim oCmd As New SqlCommand(sQry, oCnn)
oCnn.Open()

'Transaction nesnesi oluşturalım
Dim oTrs As SqlTransaction = oCnn.BeginTransaction()
'Transaction nesnesini Command nesnesiyle ilişkilendirelim
oCmd.Transaction = oTrs

Try
    oCmd.ExecuteNonQuery()
'Sorgu başarıyla yürütüldüğü için işlemi kalıcı yapalım
    oTrs.Commit()
Catch
'Sorgu başarısız olduğu için işlemi geri alalım
    oTrs.Rollback()
Finally
'Her durumda bağlantıyı kapat
    oCmd.Dispose()
    oCnn.Close()
End Try
SqlConnection oCnn = new SqlConnection(CnnStr);
string sQry = "UPDATE Musteri SET AdSoyad='Ayşe Güler' WHERE MusteriId=3;";
SqlCommand oCmd = new SqlCommand(sQry, oCnn);
oCnn.Open();

//Transaction nesnesi oluşturalım
SqlTransaction oTrs = oCnn.BeginTransaction();
//Transaction nesnesini Command nesnesiyle ilişkilendirelim
oCmd.Transaction = oTrs;

try
{
    oCmd.ExecuteNonQuery();
    //Sorgu başarıyla yürütüldüğü için işlemi kalıcı yapalım
    oTrs.Commit();
}
catch
{
    //Sorgu başarısız olduğu için işlemi geri alalım
    oTrs.Rollback();
}
finally {
    //Her durumda bağlantıyı kapat
    oCmd.Dispose();
    oCnn.Close();
}

Görünürde bir hata olmadığı için bu şekilde UPDATE cümlesi başarıyla sonuçlanır. “SQL Server Profiler” aracında transaction eventlerini incelediğimizde veritabanı sunucusu tarafından da transaction işleminin uygulandığını görmüş oluruz.

İşlemin gerçekten transaction yönetimini kullanıp kullanmadığını test etmek için query’i execute ettikten sonra sisteme hata verdirelim.

Try
    oCmd.ExecuteNonQuery()
'Burada sistem hata versin.
    Throw New Exception("Hata Oluştu.")
'Sorgu başarıyla yürütüldüğü için işlemi kalıcı yapalım
    oTrs.Commit()
Catch
'Sorgu başarısız olduğu için işlemi geri alalım
    oTrs.Rollback()
Finally
'Her durumda bağlantıyı kapat
    oCmd.Dispose()
    oCnn.Close()
End Try
try
{
    oCmd.ExecuteNonQuery();
    //Burada sistem hata versin.
    throw new Exception("Hata Oluştu.");
    //Sorgu başarıyla yürütüldüğü için işlemi kalıcı yapalım
    oTrs.Commit();
}
catch
{
    //Sorgu başarısız olduğu için işlemi geri alalım
    oTrs.Rollback();
}


Örneğimizi biraz daha geliştirip aynı transaction bünyesinde çalışacak iki Command nesnesi kullanalım. İlk Command nesnesi, Musteri tablosundaki 1 nolu müşterinin kaydını, ikinci Command nesnesi, Makale tablosundaki 1 nolu makalenin kaydını güncelleyecek.

Dim oCnn As New SqlConnection(CnnStr)
Dim sQry1 As String = "UPDATE Musteri SET AdSoyad='Ayşe Güler1' WHERE MusteriId=3;"
Dim sQry2 As String = "UPDATE Makale SET YazarAd='Ahmet Kaymaz1' WHERE MakaleId=1;"
Dim oCmd1 As New SqlCommand(sQry1, oCnn)
Dim oCmd2 As New SqlCommand(sQry2, oCnn)
oCnn.Open() 

'Transaction nesnesi oluşturalım
Dim oTrs As SqlTransaction = oCnn.BeginTransaction()
'Her iki command nesnesini oTrs ile ilişkilendirelim
oCmd1.Transaction = oTrs
oCmd2.Transaction = oTrs 

Try
    oCmd1.ExecuteNonQuery()
    oCmd2.ExecuteNonQuery()
    oTrs.Commit()
Catch
    oTrs.Rollback()
Finally
    oCmd1.Dispose()
    oCmd2.Dispose()
    oCnn.Close()
End Try
SqlConnection oCnn = new SqlConnection(CnnStr);
string sQry1 = "UPDATE Musteri SET AdSoyad='Ayşe Güler1' WHERE MusteriId=3";
string sQry2 = "UPDATE Makale SET YazarAd='Ahmet Kaymaz1' WHERE MakaleId=1";
SqlCommand oCmd1 = new SqlCommand(sQry1, oCnn);
SqlCommand oCmd2 = new SqlCommand(sQry2, oCnn);
oCnn.Open();

//Transaction nesnesi oluşturalım
SqlTransaction oTrs = oCnn.BeginTransaction();
//Her iki command nesnesini oTrs ile ilişkilendirelim
oCmd1.Transaction = oTrs;
oCmd2.Transaction = oTrs;

try
{
    oCmd1.ExecuteNonQuery();
    oCmd2.ExecuteNonQuery();
    oTrs.Commit();
}
catch
{
    oTrs.Rollback();
}
finally {
    oCmd1.Dispose();
    oCmd2.Dispose();
    oCnn.Close();
}

Bu iki query, bu haliyle sorunsuz çalışacaktır. Transaction yönetiminin etkisini görmek için ikinci query’imizde bilinçli bir hata yapalım. Makale tablosunda olmayan bir kolonu güncelleyemeye çalışalım.

Dim sQry1 As String = "UPDATE Musteri SET AdSoyad='Ayşe Güler1' WHERE MusteriId=3;"
Dim sQry2 As String = "UPDATE Makale SET OlmayanKolon='Ahmet Kaymaz' WHERE MakaleId=1;"
string sQry1 = "UPDATE Musteri SET AdSoyad='Ayşe Güler1' WHERE MusteriId=3";
string sQry2 = "UPDATE Makale SET OlmayanKolon='Ahmet Kaymaz' WHERE MakaleId=1";

Bu iki query, aynı transaction bünyesinde çalıştığı için ikinci query’nin başarısız olmasından dolayı ilk query, geri alınır.

Farklı veritabanı sunucusu üzerinde yapılan işlemler için Distributed (Dağıtık) Transaction yönetimi kullanılır. Dağıtık transaction yönetimi, Microsoft’un COM+ teknolojisinin “Component Services” servisi tarafından gerçekleştirilir. Bu yöntem, programatik olarak zor olduğu için sonraki yazıda buna alternatif olarak kullanılan ADO.NET 2.0 ile birlikte gelmiş transaction yaklaşımını inceleyeceğiz.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Time limit is exhausted. Please reload CAPTCHA.