15 Kasım 2011 Salı

C# LINQ Join Method

Linq içerisinde karşımıza çıkan metotlardan birisi de Join metodudur. Adından da anlaşılacağı üzere, SQL tarafından aşina olduğumuz join işlemlerini gerçekleştirmemizi sağlar.

Veri tabanı içerisinde Urun ve Kategori adında iki tablomuz olduğunu düşünelim. Kategori Tablosunda KategoriId ve KategoriAd, Urun tablosunda ise UrunId,UrunAd ve KategoriId kolonları olsun. Urun adlarını ve o ürünün bağlı olduğu kategoriyi ekranda görüntülemek isteyelim.

SQL tarafında bu işi basit bir join işlemi ile gerçekleştirebiliriz.

SELECT U.UrunAd,K.KategoriAd FROM Urun U

JOIN Kategori K ON U.KategoriId=K.KategoriId

Yukarıdaki script’I çalıştırdığımızda ekranda ürünlerin ve bağlı oldukları kategorilerin adlarını göreceğiz.

Şimdi de bu işi LINQ ile nasıl yapabileceğimizi ele alalım. Urun ve Kategori adında iki sınıfımız olsun.

public class Urun

    {

        public int UrunId { get; set; }

        public string UrunAd { get; set; }

        public int KategoriId { get; set; }

 

        public Urun(int id, string ad, int kategoriId)

        {

            UrunId = id;

            UrunAd = ad;

            KategoriId = kategoriId;

        }

    }

 

    public class Kategori

    {

        public int KategoriId { get; set; }

        public string KategoriAd { get; set; }

 

        public Kategori(int kategoriId, string kategoriAd)

        {

            KategoriId = kategoriId;

            KategoriAd = kategoriAd;

        }

    }

Program sınıfı içerisinde KategorileriGetir ve UrunleriGetir adında iki metot yazalım. Metotların işlevleri, veritabanındaki Urun ve Kategori tablolarındaki dataları bir koleksiyona doldurmak olarak düşünülebilir. Bir veri tabanına bağlanmak yerine, sembolik olarak data çekme işlemi gerçekleştiriyor olacağız.

class Program

    {

        static List<Kategori> KategorileriGetir()

        {

            List<Kategori> kategoriList = new List<Kategori>();

 

            kategoriList.AddRange(new Kategori[]

            {

                new Kategori(1, "Bilgisayar"),

                new Kategori(2, "Telefon"),

                new Kategori(3, "Beyaz Eşya"),

                new Kategori(4,"Mobilya"),

            });

 

            return kategoriList;

        }

 

        static List<Urun> UrunleriGetir()

        {

            List<Urun> urunler = new List<Urun>();

 

            urunler.AddRange(new Urun[]

            {

                new Urun(1,"Monitör",1),

                new Urun(2,"Klavye",1),

                new Urun(3,"IPhone",2),

                new Urun(4,"Samsung Galaxy",2),

                new Urun(5,"Buzdolabı",3),

                new Urun(6,"Çamaşır Makinesi",3),

                new Urun(7,"HTC",2),

                new Urun(8,"Bulaşık Makinesi",3),

                new Urun(9,"Laptop",1),

                new Urun(10,"Mouse",1),

                new Urun(11,"Masa",4),

                new Urun(12,"Sandalye",4),

                new Urun(13,"USB",1)

            });

 

            return urunler;

        }

    }

Urun nesnelerinde yer alak KategoriId property’si, sembolik olarak Kategori tablosundaki KategoriId’yi referans etmektedir. Şu anda böyle bir ilişki kurmadık ancak örneğimizi;, veri tabanında birbirlerine bağlı iki tablo arasındaki ilişkiyi baz alarak düşünmeye çalışalım.

Şimdi Main metodu içerisinde urunler ve kategoriler adında iki koleksiyon oluşturalım ve Join metodunu kullanarak işlemimizi gerçekleştirelim. Join metodu IEnumerable<T> interface’ini implement eden tipler üzerinden erişilebilen genişletilimiş(extension) bir metottur.

İlk olarak lambda syntax’ına alışık olmayan için klasik LINQ sorgusu şeklinde yazalım.

static void Main(string[] args)

        {

            List<Kategori> kategoriler = KategorileriGetir();

            List<Urun> urunler = UrunleriGetir();

 

            var query = from u in urunler

                        join k in kategoriler on u.KategoriId equals k.KategoriId

                        select new { UrunAd = u.UrunAd, KategoriAd = k.KategoriAd };

 

            foreach (var result in query)

            {

                Console.WriteLine("Ürün Adı : {0} , Kategori : {1}", result.UrunAd, result.KategoriAd);

            }

        }

Lambda syntax’ı ile yazalım.

static void Main(string[] args)

        {

            List<Kategori> kategoriler = KategorileriGetir();

            List<Urun> urunler = UrunleriGetir();

 

            var query = urunler.Join(kategoriler, //urunlerler yabancı anahtarı içeren tablo, kategoriler ise ana anahtarı içeriyor.

                        urun => urun.KategoriId, //Foreign Key, yani Urun tablosundaki KategoriId

                        kategori => kategori.KategoriId, //Primary Key, yani Kategori tablosundaki KategoriID

                        (urun, kategori) => new { urun, kategori })

                        .Select(result => new { UrunAd = result.urun.UrunAd, KategoriAd = result.kategori.KategoriAd });

 

            foreach (var result in query)

            {

                Console.WriteLine("Ürün Adı : {0} , Kategori : {1}", result.UrunAd, result.KategoriAd);

            }

        }

Ekran çıktısı aşağıdaki gibi olacaktır.

image

Burada Join metodunu urunler adlı koleksiyon üzerinden çağırdık. Dolayısı ile satırların eşleştirilmesi Urun nesnelerine göre yapılmış durumdadır. Tıpkı SQL tarafında olduğu gibi tam tersini yapsaydık, eşleştirme işlemi kategori nesneleri baz alınarak yapılacaktı. Dilerseniz bunu da örnek üzerinde görelim.

static void Main(string[] args)

        {

            List<Kategori> kategoriler = KategorileriGetir();

            List<Urun> urunler = UrunleriGetir();

          

            var query2 = kategoriler.Join(urunler, //kategoriler ana anahtarı, urunler de yabancı anahtarı içeriyor.

                                  k => k.KategoriId, // primary key

                                  u => u.KategoriId, // foreign key

                                  (k, u) => new { k, u })

                                  .Select(result => new { UrunAd = result.u.UrunAd, KategoriAd = result.k.KategoriAd });

 

            foreach (var result in query2)

            {

                Console.WriteLine("Ürün Adı : {0} , Kategori : {1}", result.UrunAd, result.KategoriAd);

            }

        }

image

Görüldüğü gibi, önce kategori tablosu baz alınarak, her bir kategorideki ürünler listelenmiş durumdadır.

Join metodundan geriye sorguanabilir bir nesne döndürdüğünden dolayı, üzerinden LINQ metotlarına erişebiliriz. Mesela yaptığımız bu Join işleminden sonra ürünleri kategorilerine göre gruplayalım ve her bir kategorideki toplam ürün sayısını ekrana yazdıralım.

Klasik LINQ sorgusu ile,

static void Main(string[] args)

        {

            List<Kategori> kategoriler = KategorileriGetir();

            List<Urun> urunler = UrunleriGetir();

 

            var query = from u in urunler

                        join k in kategoriler on u.KategoriId equals k.KategoriId

                        group k by k.KategoriAd into grup

                        select new { KategoriAd = grup.Key, UrunAdet = grup.Count() };

 

            foreach (var result in query)

            {

                Console.WriteLine("Ürün Adı : {0} , Kategori : {1}", result.KategoriAd, result.UrunAdet);

            }

        }

Lambda syntax’ı ile

static void Main(string[] args)

        {

            List<Kategori> kategoriler = KategorileriGetir();

            List<Urun> urunler = UrunleriGetir();

 

            var query = urunler.Join(kategoriler,

                        urun => urun.KategoriId,

                        kategori => kategori.KategoriId,

                        (urun, kategori) => new { urun, kategori })

                        .Select(result => new { UrunAd = result.urun.UrunAd, KategoriAd = result.kategori.KategoriAd })

                        .GroupBy(grup => grup.KategoriAd);

 

            foreach (var result in query)

            {

                Console.WriteLine("Kategori Adı : {0} - Ürün Sayısı : {1}", result.Key, result.Count());

            }

        }

Ekran çıktısı aşağıdaki gibi olacaktır.

 

image



2 yorum:

Adsız dedi ki...

labda sorgusunda (urun, kategori) => new { urun, kategori }) kısmına nasıl koşul verebiliriz.

Özetle LEFT OUTER JOIN urun.x on kategori.y AND kategori=123
Şeklinde nasıl tanımlama yapabiliriz.

Recep Orhan dedi ki...
Bu yorum yazar tarafından silindi.

Yorum Gönder