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

C#, VB.NET, ASP.NET Add comments

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.

  • Leave a Reply

    WP Theme & Icons by N.Design Studio
    Entries RSS Comments RSS Giriş