DataTable’de Değişen Kayıtların Bilgisi [VB.NET, C#]

DataTable, DataSet, DataRow gibi nesnelerdeki satırların durumu hakkında bilgi almak herhangi bir güncelleme olmuşsa hangi aşamada olduğunu öğrenmek için System.Data.DataRowState ve System.Data.DataRowVersion kavramları kullanılır.
DataRowState, veri tablosundaki her satırın durumunu belirtir. Özellikle satır güncelleme işlemlerini yönetmek amacıyla kullanılır. Her satırın bir RowState değeri vardır. DataRowState, aşağıdaki değerleri alabilir.

Added: Sözkonusu satır, DataRowCollection koleksiyonuna eklendi ve henüz AcceptChanges() metodu çağrılmamış.
Delete: DataRow nesnesinin Delete() metodu kullanılarak veri tablosundan silinmiş.
Detached: Bu satıra ait DataRows nesnesi oluşturulmuş fakat henüz DataRowCollection koleksiyonuna eklenmemiş yani veri tablosuna yansıtılmamış. Bu durum, satırın, oluşturulma ve Add() metoduyla DataTable’e eklenme aşamaları arasında olduğunu gösterir.
Modified: Satırda güncelleme yapılmış ama güncelleme onaylanmamış yani henüz AcceptChanges() metodu çağrılmamış.
Unchanged: Bu satır, başından beri veya AcceptChanges() metodunun çağrılmasından bu yana değişmemiş.
Bu seçenekleri kullanarak herhangi bir kayıt satırının hangi aşamada olduğunu, yani güncelleniyor, güncellenmiş veya güncellenmesi iptal edilmiş olup olmadığını kontrol edebiliriz.

'Yeni bir DataRow oluştur.
oDr = oDt.NewRow()
'Detached row
Console.WriteLine("NewRow() : " & oDr.RowState)

'Satırı, tabloya ekleyelim.
oDt.Rows.Add(oDr)
'Added row
Console.WriteLine("Rows.Add() : " & oDr.RowState)

'Değişiklikleri onaylayalım
oDt.AcceptChanges()
'Unchanged row.
Console.WriteLine("AcceptChanges() : " & oDr.RowState)

'Satırın AdSoyad kolonunu güncelleyelim.
oDr("AdSoyad") = "Ahmet Kaymaz"
'Modified row.
Console.WriteLine("Modified : " & oDr.RowState)

'Bu satırı silelim
oDr.Delete()
'Deleted row.
Console.WriteLine("Deleted : " & oDr.RowState)
//Yeni bir DataRow oluştur.
oDr = oDt.NewRow();
//Detached row
Console.WriteLine("NewRow() : " + oDr.RowState);

//Satırı, tabloya ekleyelim.
oDt.Rows.Add(oDr);
//Added row
Console.WriteLine("Rows.Add() : " + oDr.RowState);

//Değişiklikleri onaylayalım
oDt.AcceptChanges();
//Unchanged row.
Console.WriteLine("AcceptChanges() : " + oDr.RowState);

//Satırın AdSoyad kolonunu güncelleyelim.
oDr["AdSoyad"] = "Ahmet Kaymaz";
//Modified row.
Console.WriteLine("Modified : " + oDr.RowState);

//Bu satırı silelim
oDr.Delete();
//Deleted row.
Console.WriteLine("Deleted : " + oDr.RowState);

NewRow() : Detached
Rows.Add() : Added
AcceptChanges() : Unchanged
Modified : Modified
Deleted : Deleted

Bilindiği gibi dataset içindeki veri tablosundan kayıt silmek için Remove() veya Delete() metodu kullanılır. Remove() metodu, sözkonusu satırı olduğu gibi satır koleksiyonundan uçurur ve satırın RowState’inden bir değişiklik yapmaz, Delete() ise satır sadece silinecek olarak işaretler ve RowState’ini “Deleted” olarak set eder.

oDt.AcceptChanges()
Dim oDs As New DataSet()
oDs.Tables.Add(oDt)
'İlk satırı Delete() ile silelim
oDt.Rows(0).Delete() 'Deleted
Console.WriteLine(oDt.Rows(0).RowState.ToString()) 'Deleted
Console.WriteLine(oDs.HasChanges()) 'True
'İkinci satırı Remove() ile silelim
oDt.Rows.Remove(oDt.Rows(1))
Console.WriteLine(oDt.Rows(1).RowState.ToString()) 'Unchanged
Console.WriteLine(oDs.HasChanges()) 'False
oDt.AcceptChanges();
DataSet oDs= new DataSet();
oDs.Tables.Add(oDt);
//İlk satırı Delete() ile silelim
oDt.Rows[0].Delete();//Deleted
Console.WriteLine(oDt.Rows[0].RowState);//Deleted
Console.WriteLine(oDs.HasChanges());//True
//İkinci satırı Remove() ile silelim
oDt.Rows.Remove(oDt.Rows[1]);
Console.WriteLine(oDt.Rows[1].RowState);//Unchanged
Console.WriteLine(oDs.HasChanges());//False

ADO.NET 2.0 ile birlikte tablodaki satırlar üzerinde hakimiyetimiz artırılmış oldu. DataRow türündeki bir satırın RowState durumu manual olarak değiştirilebilir. Bunun için SetAdded() ve SetModified() metodları kullanılır. Bu metodların uygulanacağı satırların RowState durumlarının Unchanged olarak set edilmiş olması lazım. Yani bu metodlardan önce AcceptChanges() metodu çağrılarak tablodaki değişikliklerin onaylanması gerekir.
DataTable üzerinde çalışma zamanında ekleme, güncelleme, silme yapabildiğimiz için bu nesneyi asıl veritabanına göndermeye çalıştığımızda veri tutarlılığının olması gerekmektedir(Concurrency Exception – eş zamanlı uyumsuzluk durumu). Yani fiziksel veritabanındaki veriler, en son bizim çektiğimiz veriler olmalı, yani başka bir kullanıcı tarafından güncelleme yapılmamış olmalı. Çünkü daha sonra açıklayacağımız üzere DataAdapter, güncellemeleri database sunucusuna yansıtmaya çalışırken güncellenmiş verilerin orijinal değerlerini koşul olarak kullanır. Dolayısıyla bu süreçte her verinin default, asıl veya değişmiş versiyonu bulunur. Bu değişiklikler hakkında bilgiyi, DataRowVersion numaralandırıcısı verir. Herhangi bir satırda güncelleme yapıldığı zaman o satırın orijinal ve güncel olmak iki versiyonu oluşur. Bir satırın sözkonusu veriyonlarının olup olmadığı boolean türünde değer döndüren HasVersion() metoduyla kontrol edilir.

Current: Satırın en sonki güncel değeri içerdiği versiyonu. Eğer satırın RowState property’si Deleted değerindeyse DataRowVersion için Current değeri oluşmaz.
Original: Satırın orijinal değeri içerdiği versiyonu. Eğer satırın RowState property’si Added modundaysa DataRowVersion için Original değeri oluşmaz.
Proposed: Yapılması düşünülen, niyetlenen değişikliği(proposed change) belirtir. Bunlar, DataRow nesnesinin BeginEdit() ve EndEdit() veya CancelEdit() metodları arasında yapılan değişikliklerdir. Yani BeginEdit() metodu çağrılmıştır fakat EndEdit() veya CancelEdit() metodları çağrılmamıştır. CancelEdit() metodun çağrılmasıyla satırın proposed sürümü silinir. Bu yüzden bir satırın proposed versiyonuna RowChanging, ColumnChanged gibi eventlere ait metodlarda erişilebilir.
Default: Bu değer, o satır için varsayılan satır versiyonunu(default row version) ne olacağını belirtir. Eğer satırın RowState property’si, Added, Modified veya UnChanged değerindeyse bu satırın default row versiyonu Current olandır. Eğer RowState property’si Deleted değerindeyse satırın default row versiyonu Original olur. Eğer RowState property’si Detached modundaysa satırın default row versiyonu Proposed olur.
Herhangi bir satırın bu değerlerdeki satır versiyonuna erişmek için DataRow nesnesinin indexer’i kullanılır.

Default Public ReadOnly Property Item( _
    ByVal column As DataColumn, _
    ByVal version As DataRowVersion _
) As Object

Default Public ReadOnly Property Item( _
    ByVal columnIndex As Integer, _
    ByVal version As DataRowVersion _
) As Object

Default Public ReadOnly Property Item( _
    ByVal columnName As String, _
    ByVal version As DataRowVersion _
) As Object
public object this[DataColumn column, DataRowVersion version]{get;}
public object this[int columnIndex, DataRowVersion version] {get;}
public object this[string columnName, DataRowVersion version] {get;}
'ColumnChanged event'i için bir handler tanımlayalım.
AddHandler oDt.ColumnChanged, _
    New DataColumnChangeEventHandler(AddressOf KolonDegisti)
'İlk değeri Ayşe olan bu kaydı Zeynep olarak güncelleyelim.
oDt.Rows(1)("AdSoyad") = "Zeynep Korkmaz"

Sub KolonDegisti(ByVal sender As Object, _
    ByVal e As DataColumnChangeEventArgs)
    Console.WriteLine(e.Row("AdSoyad"))
    Console.WriteLine(e.Row("AdSoyad", DataRowVersion.Current))
    Console.WriteLine(e.Row("AdSoyad", DataRowVersion.Original))
    Console.WriteLine(e.Row("AdSoyad", DataRowVersion.[Default]))
    Console.WriteLine(e.Row("AdSoyad", DataRowVersion.Proposed))
End Sub
//ColumnChanged event'i için bir handler tanımlayalım.
oDt.ColumnChanged += new DataColumnChangeEventHandler(KayitDegisti);
//İlk değeri Ayşe olan bu kaydı Zeynep olarak güncelleyelim.
oDt.Rows[1]["AdSoyad"] = "Zeynep Korkmaz";

static void KayitDegisti(object sender, DataColumnChangeEventArgs e)
{
    Console.WriteLine(e.Row["AdSoyad"]);
    Console.WriteLine(e.Row["AdSoyad", DataRowVersion.Current]);
    Console.WriteLine(e.Row["AdSoyad", DataRowVersion.Original]);
    Console.WriteLine(e.Row["AdSoyad", DataRowVersion.Default]);
    Console.WriteLine(e.Row["AdSoyad", DataRowVersion.Proposed]);
}

Zeynep Korkmaz
Ayşe Korkmaz - Current
Ayşe Korkmaz - Original
Zeynep Korkmaz - Default
Zeynep Korkmaz - Proposed

Tablodaki Değişiklikleri İzlemek
DataTable ile ilgili bahsececeğimiz diğer konu da tabloda yapılan değişikliklerin izlenmesidir. Veri tablosundaki eklenmiş, güncellenmiş veya silinmiş satırları yakalamak için DataTable nesnesinin GetChanges() metodu kullanılır. Bu metod, veri tablosundaki AcceptChanges() metodunun çağrılmasından sonraki tüm değişikliklerin bulunduğu bir DataTable nesnesi döndürür.

'Önceki tüm değişiklikleri onaylayalım
oDt.AcceptChanges()
'İlk değeri Ayşe olan 2.satırı Zeynep olarak güncelleyelim.
oDt.Rows(1)("AdSoyad") = "Zeynep Korkmaz"

'Yeni bir satır ekleyelim.
oDr = oDt.NewRow()
oDr("AdSoyad") = "Metin Güneş"
oDr(2) = "10/10/1950"
oDt.Rows.Add(oDr)

'Tablonun 2.satırını silelim
oDt.Rows(1).Delete()
'İlk satırını Remove() ile silelim
oDt.Rows.Remove(oDt.Rows(0))

'Kaç satırın değiştiğini öğrenelim
'Değişiklik yapılmadığı zaman sistemin hata vermemesi için böyle bir kontrol gerekli
If oDt.GetChanges() Is Nothing Then
    Console.WriteLine("Değişmiş satır bulunamadı.")
Else
    Console.WriteLine("Değişmiş satır sayısı: {0}", oDt.GetChanges().Rows.Count)
End If

'Değişmiş kayıtları oTb nesnesine alalım
Dim oTb As DataTable = oDt.GetChanges()

For Each oDr1 As DataRow In oTb.Rows
'Silinmiş kayıtların şu anki değerleri olmadığı için
    If oDr1.RowState = DataRowState.Deleted Then
        Console.Write("MusteriId: {0} ", _
            oDr1("MusteriId", DataRowVersion.Original))
        Console.Write("" Ad Soyad: {0}", _
            oDr1("AdSoyad", DataRowVersion.Original))
    Else
        Console.Write("MusteriId: {0} ", oDr1("MusteriId"))
        Console.Write("" Ad Soyad: {0}", oDr1("AdSoyad"))
    End If
    Console.Write(" " Durum: {0}", oDr1.RowState)
    Console.WriteLine()
Next
//Önceki tüm değişiklikleri onaylayalım
oDt.AcceptChanges();
//İlk değeri Ayşe olan 2.satırı Zeynep olarak güncelleyelim.
oDt.Rows[1]["AdSoyad"] = "Zeynep Korkmaz";

//Yeni bir satır ekleyelim.
oDr = oDt.NewRow();
oDr["AdSoyad"] = "Metin Güneş";
oDr[2] = "10/10/1950";
oDt.Rows.Add(oDr);

//Tablonun 2.satırını silelim
oDt.Rows[1].Delete();
//İlk satırını Remove() ile silelim
oDt.Rows.Remove(oDt.Rows[0]) ;

//Kaç satırın değiştiğini öğrenelim
//Değişiklik yapılmadığı zaman sistemin hata vermemesi için böyle bir kontrol gerekli
if (oDt.GetChanges() == null)
    Console.WriteLine("Değişmiş satır bulunamadı.");
else
    Console.WriteLine("Değişmiş satır sayısı: {0}",
        oDt.GetChanges().Rows.Count);

//Değişmiş kayıtları oTb nesnesine alalım
DataTable oTb = oDt.GetChanges();

foreach (DataRow oR in oTb.Rows)
{
    //Silinmiş kayıtların şu anki değerleri olmadığı için
    if (oR.RowState == DataRowState.Deleted)
    {
        Console.Write("MusteriId: {0} ",
            oR["MusteriId", DataRowVersion.Original]);
        Console.Write("" Ad Soyad: {0}",
            oR["AdSoyad", DataRowVersion.Original]);
    }
    else
    {
        Console.Write("MusteriId: {0} ", oR["MusteriId"]);
        Console.Write("" Ad Soyad: {0}", oR["AdSoyad"]);
    }
    Console.Write(" " Durum: {0}", oR.RowState);
    Console.WriteLine();
}

Değişmiş satır sayısı: 2
MusteriId: 1 " Ad Soyad: Ayşe Korkmaz " Durum: Deleted
MusteriId: 2 " Ad Soyad: Metin Güneş " Durum: Added

GetChanges() metodu, overload edilmiş olup DataRowState türünde parametre alan versiyonu da kullanılabilir. Bu durumda sadece belli durumlardaki satırları döndürür.

If oDt.GetChanges(DataRowState.Added) Is Nothing Then
    Console.WriteLine("Eklenmiş satır bulunamadı.")
Else
    Console.WriteLine("Eklenmiş satır sayısı: {0}", oDt.GetChanges().Rows.Count)
End If

'Sadece yeni eklenmiş kayıtları oTb nesnesine alalım
Dim oTb As DataTable = oDt.GetChanges(DataRowState.Added)

For Each oDr1 As DataRow In oTb.Rows
    Console.Write("MusteriId: {0} ", oDr1("MusteriId"))
    Console.Write("" Ad Soyad: {0}", oDr1("AdSoyad"))
    Console.Write(" " Durum: {0}", oDr1.RowState)
    Console.WriteLine()
Next
if (oDt.GetChanges(DataRowState.Added) == null)
    Console.WriteLine("Eklenmiş satır bulunamadı.");
else
    Console.WriteLine("Eklenmiş satır sayısı: {0}",
        oDt.GetChanges().Rows.Count);

//Sadece yeni eklenmiş kayıtları oTb nesnesine alalım
DataTable oTb = oDt.GetChanges(DataRowState.Added);

foreach (DataRow oR in oTb.Rows)
{
    Console.Write("MusteriId: {0} ", oR["MusteriId"]);
    Console.Write("" Ad Soyad: {0}", oR["AdSoyad"]);
    Console.Write(" " Durum: {0}", oR.RowState);
    Console.WriteLine();
}

Eklenmiş satır sayısı: 2
MusteriId: 2 " Ad Soyad: Metin Güneş " Durum: Added

Görüldüğü gibi GetChanges() metodu aracılığıyla dirty data denilen değişikliği henüz onaylanmamış kayıtları yakalama şansına sahibiz. Bu kayıtları, AcceptChanges() veya RejectChanges() metodlarını çağırdıktan sonra artık takip edemeyiz. Çünkü bu metodlar, veri tablosunda tutulan tüm değişiklik bilgileri siler.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir