DataTable’da Distinct ve TOP N ÖrneÄŸi

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

ADO.NET’in önemli üyesi olan DataTable nesnesi üzerinde arama yaparken distinct (tekilleÅŸtirme) veya top n (üstten belli sayıda satır seçme) iÅŸlemlerine ihtiyaç duyabiliriz. Bu iÅŸlemleri çoÄŸu zaman VTYS üzerinde yapmak mantıklı görünse de özellikle baÄŸlantısız katman iÅŸlemlerinde veritabanına gitmeksizin bu iÅŸlemleri yapmak iÅŸlemleri hızlandırır. Bu yazıda bununla ilgili basit bir örnek vereceÄŸiz.

Distinct işlemi için DataTable nesnesinin ToTable() yordamı kullanılır. ADO.NET 2.0 ile birlikte gelmiş olan bu yordam, DataView içerisindeki kayıtları yeni bir DataTable nesnesine aktarmanın en kısa yoludur. ToTable() yordamı, overload edilmiş olup verileri olduğu gibi tabloya aktarabildiği gibi verilecek parametreler doğrultusunda belirli kolon veya kolonlar üzerinde DISTINCT işlemini uygulayarak verileri tabloya aktarabilir. ToTable() yordamının prototipi şu şekildedir;

Public Function ToTable() As DataTable
Public Function ToTable(ByVal tableName As String) As DataTable
Public Function ToTable(ByVal distinct As Boolean, _
    ByVal ParamArray columnNames As String()) As DataTable
Public Function ToTable(ByVal tableName As String, _
    ByVal distinct As Boolean, _
    ByVal ParamArray columnNames As String()) As DataTable
public DataTable ToTable();
public DataTable ToTable(string tableName);
public DataTable ToTable(bool distinct,
    params string[] columnNames);
public DataTable ToTable(string tableName, bool distinct,
    params string[] columnNames);

Bu yordamı bir örnek üzerinde gösterelim.

Dim oDt As New DataTable("Table")
oDt.Columns.Add("No")
oDt.Columns.Add("AdSoyad")

oDt.Rows.Add("10", "Ahmet")
oDt.Rows.Add("10", "Ahmet")
oDt.Rows.Add("11", "Mehmet")

Dim oDv As DataView = oDt.DefaultView
oDv.RowFilter = "No>9"

'View'deki kayıtları No ve AdSoyad kolonlarına göre distinct yapıp Tablo ismindeki yeni bir tabloya aktarsın
Dim oTb As DataTable = oDv.ToTable("Tablo", True, _
    New String() {"No", "AdSoyad"})

For Each oDr As DataRow In oTb.Rows
    Console.WriteLine(oDr("No") + " " + oDr("AdSoyad"))
Next
DataTable oDt = new DataTable("Table");
oDt.Columns.Add("No");
oDt.Columns.Add("AdSoyad");

oDt.Rows.Add("10", "Ahmet");
oDt.Rows.Add("10", "Ahmet");
oDt.Rows.Add("11", "Mehmet");

DataView oDv = oDt.DefaultView;
oDv.RowFilter = "No>9";

//View'deki kayıtları No ve AdSoyad kolonlarına göre distinct yapıp Tablo ismindeki yeni bir tabloya aktarsın
DataTable oTb = oDv.ToTable("Tablo", true,
    new string[] {"No","AdSoyad"});

foreach(DataRow oDr in oTb.Rows)
    Console.WriteLine(oDr["No"] +" "+ oDr["AdSoyad"]);

10 Ahmet
11 Mehmet

EÄŸer burada distinct iÅŸlemini yaptırmamış olsaydık. “Ahmet” kaydı iki defa yazılacaktı.

Bir veri tablosunda en üstteki veya en alttaki n tane kaydı okumak isteyebiliriz. DataTable veya DataView nesneleri üzerinde doÄŸrudan “TOP N” iÅŸlemini yaptıracak bir yordam bulunmamaktadır. Bunun yapmanın en kolay yolu, DataView veya DataTable kayıtlarını döngüye sokarak istenilen kayıt kadar okuma yapılıp okunan kayıtların yeni bir nesneye aktarılmasıdır. EÄŸer tabloda arada eksik kayıt içermeyen identity kolonu varsa bu kolon referans alınarak kolayca “TOP N” iÅŸlemi yapılabilir (DataTable.Select ("IdentiyKolon<N") gibi). Fakat tablodaki tüm kayıtlar arasındaki deÄŸil belirli ÅŸartlara uyan kayıtlar arasından seçim yapılacak o zaman en mantıklısı döngü yöntemini kullanmaktır.

Sub Main()
    'Tek kolonlu bir tablo
    Dim oDt As New DataTable("Tablo")
    oDt.Columns.Add(New DataColumn("No", GetType(Int32)))
    oDt.Columns.Add(New DataColumn("Aciklama"))

    '10 kayıt ekleyelim
    Dim oDr As DataRow
    For i As Integer = 0 To 9
        oDr = oDt.NewRow()
        oDr("No") = (i + 1)
        oDr("Aciklama") = "Kayit " & (i + 1)
        oDt.Rows.Add(oDr)
    Next

    'DataView nesnesi oluşturalım
    Dim oDv As New DataView(oDt)
    'Numarası, 4'ten büyük olanları alalım
    oDv.RowFilter = "No>4"
    oDv.Sort = "Aciklama DESC"

    'Tabloda ilk 5 satırı seçelim.
    Dim oDvTop5 As DataView = GetTopRows(oDv, 5)
    Console.WriteLine("----Tablodaki İlk 5 Satır----")
    Console.WriteLine("[No]" & Chr(9) & "[Aciklama]")
    Console.WriteLine("----" & Chr(9) & "----------")

    For i As Integer = 0 To oDvTop5.Count - 1
        Console.WriteLine(oDv(i)("No") & "" & Chr(9) & _
            "" & oDv(i)("Aciklama"))
    Next
    Console.ReadLine()
End Sub

'oDv parametresi, üzerinde işlem yapacağı DataView'i belirtir
'N parametresi de oDv kaynağından kaç kayıt alması gerektiğini bildirir
Function GetTopRows(ByVal oDv As DataView, ByVal N As Integer) As DataView
    'Ara bir DataTable oluşturalım
    'Bu tablo, kaynak tablonun aynısı olmalıdır
    Dim oTbHedef As DataTable = oDv.Table.Clone()
    'Kaç kayıt isteniyorsa kaynak view'den o kadar okuyalım
    'Eğer istenilen kayıt sayısı, kaynak tablodaki satır sayısını aşıyorsa sistem hata vermesin
    If N >= oDv.Count Then
        N = oDv.Count
    End If
    For i As Integer = 0 To N - 1
        oTbHedef.ImportRow(oDv(i).Row)
    Next

    Return New DataView(oTbHedef)
End Function
static void Main(string[] args) {
    //Tek kolonlu bir tablo
    DataTable oDt = new DataTable("Tablo");
    oDt.Columns.Add( new DataColumn("No",typeof(Int32)));
    oDt.Columns.Add(new DataColumn("Aciklama"));

    //10 kayıt ekleyelim
    DataRow oDr;
    for (int i = 0; i < 10; i++) {
        oDr = oDt.NewRow();
        oDr["No"] = (i+1);
        oDr["Aciklama"] = "Kayit " + (i + 1);
        oDt.Rows.Add(oDr);
    }

    //DataView nesnesi oluşturalım
    DataView oDv = new DataView(oDt);
    //Numarası, 4'ten büyük olanları alalım
    oDv.RowFilter = "No>4";
    oDv.Sort = "Aciklama DESC";

    //Tabloda ilk 5 satırı seçelim.
    DataView oDvTop5 = GetTopRows(oDv,5);
    Console.WriteLine("----Tablodaki İlk 5 Satır----");
    Console.WriteLine("[No]\t[Aciklama]");
    Console.WriteLine("----\t----------");

    for (int i = 0; i < oDvTop5.Count; i++) {
        Console.WriteLine(oDv[i]["No"] + "\t" +
            oDv[i]["Aciklama"]);
    }
    Console.ReadLine();
}//Main

//oDv parametresi, üzerinde işlem yapacağı DataView'i belirtir
//N parametresi de oDv kaynağından kaç kayıt alması gerektiğini bildirir
static DataView GetTopRows(DataView oDv, int N) {
    //Ara bir DataTable oluşturalım
    //Bu tablo, kaynak tablonun aynısı olmalıdır
    DataTable oTbHedef = oDv.Table.Clone();
    //Kaç kayıt isteniyorsa kaynak view'den o kadar okuyalım
    //Eğer istenilen kayıt sayısı, kaynak tablodaki satır sayısını aşıyorsa sistem hata vermesin
    if (N >= oDv.Count) N = oDv.Count;
    for (int i = 0; i < N; i++)
        oTbHedef.ImportRow(oDv[i].Row);

    return new DataView(oTbHedef);
}//GetTopRows

----Tablodaki İlk 5 Satır----
[No] [Aciklama]
---- ----------
9 Kayit 9
8 Kayit 8
7 Kayit 7
6 Kayit 6
5 Kayit 5

3 Responses to “DataTable’da Distinct ve TOP N ÖrneÄŸi”

  1. Serap Bircan Says:

    .net 2003′te ToTable var mı?

  2. Ahmet Kaymaz Says:

    ToTable() yordamı DataTable sınıfına ADO.NET 2.0 ile birlikte eklendi. ADO.NET 1.0 veya ADO.NET 1.1 platformunda distinct iÅŸlemi için ara DataTable’ler kullanarak gerçekleÅŸtirebilirsiniz.

  3. Turgay Says:

    Çok teşekkürler, faydalı oldu ve zaman kazandırdı.

    Selamlar.

Leave a Reply


+ 5 = 11

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