27 Nisan 2014 Pazar

Lazy Loading


   Merhaba arkadaşlar,

   Bu hafta birlikte Lazy Loading konusunu öğrenmeye çalışacağız. Lazy Loading kavramının ne olduğunu, Entity Framework konusundaki yerini örneklerle açıklamaya çalışacağım. İlk önce Lazy Loading kavramını açıklayalım. Lazy Loading genel anlamıyla bir nesnenin ihtiyaç duyulmaması halinde çağrılmaması esasına dayanmaktadır. Genel bir örnekle pekiştirirsek bir Web sitesi hayal edelim. Bu web sitesi barındırdığı bütün resimler yüklenmeden açılır. Biz sayfanın ilgili bölümlerini görüntülemeye başladığımızda yine o ilgili bölümde bulunan resimler yüklenmeye başlar. Yani resimleri görüntülemek istediğimiz zaman görüntülenmesi sağlanır. Bu da bize Web sayfasını ilk açmaya çalıştığımızda önemli bir performans katkısı sağlamış olur. Lazy Loading'in temel amacıda budur aslında.

   Lazy Loading'in Entity Framework ile kullanılma amacıda tamamen yukarıda bahsettiğim örnek ile aynıdır. Veritabanımızdaki tabloları nesneler üzerinden kontrol edebildiğimizi daha önceden öğrenmiştik. Oluşturduğumuz nesneleri ihtiyacımız olmadığı zamanlar kullanmazsak bir performans artışı sağlayacağımız şüphesiz. Peki Entity Framework yapısıyla Lazy Loading'i nasıl kullanabiliriz şimdi bunu görelim. Bunun için ilk önce bir veritabanımıza ihtiyacımız var. Örnekleri çeşitlendirmek amacıyla her yazımda farklı bir veritabanı kullanıyorum. Bu yazımda da Northwind veritabanını kullanacağım. Bunun için .bak uzantılı dosyayı buradan indirebilirsiniz. İlgili dosyayı indirdikten sonra .bak uzantılı dosyamızı MS Sql 2008 ile bağlamamız gerekiyor. Bunun için aşağıdaki adımları izlememiz gerekecek.

   Adım 1- İndirdiğimiz dosyayı C:\ klasörüne kopyalayalım.
 
   Adım 2- MS Sql 2008 de Database seçeneğine sağ tıklayıp "Restore Database..." kısmını seçelim.

Figür 1- Restore Database...

   Adım 3- Karşımıza çıkan ekrandan Device kısmını işaretleyip bilgisayarımızda bulunan Northwind veritabanını seçmek için "..." kısmına tıklıyoruz. Bu işlemleri yaptıktan sonra yeni bir pencere açılacaktır. Açılan pencereden Add butonuna basalım.

Figür 2- Veritabanı Ekleme

   Adım 4- Açılan yeni pencereden C:\ klasörüne attığımız Northwind.bak dosyamızı seçip "OK" tuşuna basıyoruz ve veritabanımızı MS Sql 2008'e eklemiş oluyoruz

Figür 3- C:\ Klasöründen Veritabanı Seçme

   Veritabanımızı ekledikten sonra şimdi gelelim örnek kodumuza. Öncelikle C# console application projesi oluşturalım. Oluşturduğumuz projeye her zaman ki gibi DataModel ekliyoruz ve kodlamaya başlıyoruz.

        class Categories
    {
        public int CategoryID { get; set; }
        public string CategoryName { get; set; }
        public string Description { get; set; }
        public string Image { get; set; }   
   }

   Category classımızı oluşturduk ve propertyleri tanımladık. Şimdi Product classımızı oluşturalım.

          class Product
     {
        public int ProductID{ get; set; }
        public string ProductName { get; set; }
       public int CategoryID { get; set; }   
     }

   Kullanacağımız attributeler için propertyleri oluşturduk.

   
         NORTHWINDEntities db = new NORTHWINDEntities();

     List<Categories> categories = db.Categories.OrderBy(c => c.CategoryName).ToList();

       
        foreach (Categories cat in categories)
                {

                    Console.WriteLine(string.Format("{0} [{1}]",
                                               cat.CategoryName,
                                               cat.Products.Count));
                    WriteProducts(cat);

                }
       static void WriteProducts(Categories category)

        {
            foreach (Products prod in category.Products)

            {

                Console.WriteLine(string.Format("\t{0}",prod.ProductName));

            }

        }
  
   Bu kodun ekran çıktısı aşağıdaki gibi olacaktır.
Figür 4- Ekran Çıktısı

   Örneğimizde Category tablosundaki tüm Categoryleri CategoryName attributesine göre sıralayarak bir list oluşturuyoruz. Artık elimizde tüm Categoryler var. Şimdi Products tablosundan da verileri getirip getirmediğini deneyebiliriz. Bunun için "foreach" ile her bir Category altındaki Product elemanlarını almaya çalışalım. Bunun için de "WriteProducts" metodunu oluşturup parametre olarak Categories olarak gönderdik ve bu metodun dönüşünde Category'yi gönderip altındaki Product elemanlarını  Console  yazdırdık.

   Sql Profiler dan arka planda çalıştırılan Sql sorgularını incelediğimizde foreach döngüsüne gelene ve Product elemanları çekilmek istenene kadar sadece tüm kategorileri getiren bir sorgu çalıştığını göreceğiz.

   Ne zamanki ürünler isteniyor o zaman Products koleksiyonu dolduruluyor.

   SELECT
   [Extent1].[CategoryID] AS [CategoryID],
   [Extent1].[CategoryName] AS [CategoryName],
   [Extent1].[Description] AS [Description],
   [Extent1].[Picture] AS [Picture]
   FROM [dbo].[Categories] AS [Extent1]

   ORDER BY [Extent1].[CategoryName] ASC

   Şimdi de kodumuzda Lazy Loading'i kapatalım ve sonuçları gözlemleyelim.

   static void Main(string[] args)
        {

            using (NorthwindEntities db = new NorthwindEntities())

            {
                db.ContextOptions.LazyLoadingEnabled = false; 
                List<Categories> categories = db.Categories.OrderBy(c => c.CategoryName).ToList(); 

                foreach (Categories cat in categories)
                {

                    Console.WriteLine(string.Format("{0} [{1}]",
                                                    cat.CategoryName,
                                                    cat.Products.Count));
                    WriteProducts(cat);

                }

            }
        }

        static void WriteProducts(Categories category)

        {
            foreach (Products prod in category.Products)

            {

                Console.WriteLine(string.Format("\t{0}",prod.ProductName));

            }

        }ORDER BY [Extent1].[CategoryName] ASC

   Entity Modellimizin ContexOptions.LazyLoadingEnabled özelliğini false olarak belirledik. ContexOptions.LazyLoadingEnabled ne için kullanıldığını öğrenmek için Visual Studio'ya sorduğumuzda bize aşağıdaki gibi cevap verecektir.


   Şimdi yapmış olduğumuz örneği açıklayacak olursak; Category elemanlarının altındaki Product propertyleri çağırılacak olursa otomatik olarak yüklenecektir. Ancak Product ile ilgili herhangi bir işlem yapılmadığı zaman veritabanından Product ile ilgili bilgilere erişim yapılmayacaktır.

Figür 5- Ekran Çıktısı-2

   Yukarıda görüldüğü gibi Lazy Loading'i kapattığımız zaman Product bilgilerine erişim olmadı. Lazy Loading'i kapatıp Category başlığı altındaki Tüm Productları listelemek istersek aşağıdaki kodu yazabiliriz.
    
   List<Categories> categories = db.Categories.Include("Products").OrderBy(c => c.CategoryName).ToList();

   Yukarıdaki kod Categoryleri alırken ilgili Productlarıda yüklememizi sağlayacaktır. Sql tarafında da sadece bir sorgu dönecek ve işlemimizi tamamlamış olacağız.

   Fakat Lazy Loading ile bu işlemi yaptığımızda her seferinde bir sorgu dönecek toplam sekiz ayrı Category içinse sekiz farklı sorgu dönecektir. Burada tercih bize kalıyor, eğer tüm kategori ve ürünleri göstermeyeceksek, belirli kategorilerin ürünlerini göstereceksek Lazy Loading kullanmak daha mantıklı.

   Bu haftaki yazımında burada sonuna geliyorum. Haftaya ki yazımda görüşmek üzere...

   Referanslar:

   1- http://www.codeproject.com/Articles/652556/Can-you-explain-Lazy-Loading
   2- http://www.integralwebsolutions.co.za/Blog/EntryId/905/Entity-Framework-5-Lazy-Eager-Explicit-Loading.aspx

20 Nisan 2014 Pazar

LinQ ile Veritabanı İşlemleri

   Merhaba arkadaşlar,

   Geçen hafta LinQ teknolojisini nasıl kullanacağımızı öğrenmiştik. Bu hafta ise LinQ teknolojisi ile birlikte bazı veritabanı işlemlerini gerçekleştirmeye çalışacağız. İlk haftalarda veritabanı işlemleri için ayrı bir veritabanı kullanmıştık. Bu hafta yapacağım programı daha kolay takip etmeniz açısından daha basit ve anlaşılır bir veritabanı kullanacağım.

  İlk olarak veritabanımızı oluşturarak işe başlayalım. MS Sql'de aşağıdaki Queryi execute edelim.

create database School;

use School;

create table Teacher(
Tid int NOT NULL IDENTITY(1,1) ,
name varchar(50),
surname varchar(50),
title varchar(50),
course varchar(50),
primary key(Tid),
)

   Yukarıdaki Query de bir okul veritabanı oluşturduk ve bu veritabanına teacher tablosu ekledik. Teacher tablosuna bazı attributeler ekledikten sonra primary key olan Tid ' yi otomatik artırması için IDENTITY(1,1) kodunu kullandık. Tablomuzu oluşturduktan sonra bu tabloya aşağıdaki şekilde veriler girelim.

Figür 1: Veritabanı Görünüm

   Veritabanımızı oluşturduktan sonra geçmiş haftalarda gösterdiğim şekilde Data Model oluşturuyoruz ve bu haftaki asıl konumuza geçiyoruz.

   Bu hafta LinQ teknolojisini kullanarak veritabanımızdaki verileri özel kurallara göre listelemeyi ve seçili olan veriyi silme işlemlerini öğreneceğiz. Bunun için ilk olarak bir form dizayn edelim ve bu form üzerinden işlemlerimizi yapalım. Formumuzun dizaynı aşağıdaki gibi olsun.

Figür 2: Form Dizayn

   Şekilde de görüldüğü gibi bir DataGridView, bir TextBox, bir Label ve iki Button kullandık ve isimlerini aşağıdaki gibi düzenledik.

DataGridView = dgvTeacher
TextBox = txtTitle
Tamam  Button = btnOnay
Sil Button = btnSil

   Formumuzu dizayn edip gerekli düzenlemeleri yaptıktan sonra şimdi belli bir kurala göre nasıl listeleme işlemi yapacağız onu görelim.

   İlk önce DataModelini oluşturduğumuz School veritabanını kullanmak için aşağıdaki kod blogunu ekleyelim.

   SchoolEntities se = new SchoolEntities();

   Daha sonra Teacher tablosundaki attributeleri kullanmak için GetTeacher classı açıp bütün attributeler için tek tek property oluşturuyoruz.

   class GetTeacher
    {
        public int Tid { get; set; }
        public string name { get; set; }
        public string surname { get; set; }
        public string title { get; set; }
        public string course { get; set; }
    }
}

Listeleme İşlemi:

   Kuralımız öğretmenlerin ünvanları olsun. Textbox'a yazacağımız ünvana göre DataGridView'da ilgili öğretmenler çıksın. Bunun için Tamam Butonun Click metodunu aşağıdaki gibi düzenleyelim.

    private void btnOnay_Click(object sender, EventArgs e)
        {
            List<GetTeacher> lst_Teacher = new List<GetTeacher>();

            lst_Teacher = (from q in se.Teachers
                           where q.title == txtTitle.Text
                           select new GetTeacher
                           {
                               Tid = q.Tid,
                               name = q.name,
                               title = q.title,
                               surname = q.surname,
                               course = q.course,
                           }).ToList();
            dgvTeacher.DataSource = lst_Teacher;

        }

   Geçen hafta anlattığım LinQ konusunda herhangi bir List<> üzerinden nasıl where, select, from gibi komutların kullanılacağını görmüştük. Yukarıda da GetTeacher classı türünde bir List oluşturduk ve bu list üzerinde where komutu ile bir koşul belirtmiş olduk. where q.title == txtTitle.Text   kodu ile TextBox dan aldığımız veriyi q.title'a eşitleyerek istediğimiz ünvanlı öğretmenlerin listelenmesini sağladık.

   ToList() metodu ise GetTeacher türünde oluşturduğumuz lst_Teacher listesine belirtiğimiz koşulu sağlayan öğretmenleri bu listeye atmamızı sağladı.

   Programımızı Yard.Doç ünvana sahip öğretmenleri sıralamak için kullanalım.

Figür 3: Yard.Doç ünvanlı Öğretmenler

Silme İşlemi:

   Silme işlemlerini yapabilmek için kullandığımız DataGridView propertylerinden Multi Select= false, SelectionMode = FullRowSelect yapıyoruz. Bu işlemi yaptıktan sonra getIndex isimli bir değer belirliyoruz.

   public string getIndex;

   Oluşturduğumuz bu string değeri bizim DataGridView'da seçtiğimiz itemin indexini tutacak ve bizde bu index üzerinden silme işlemimizi gerçekleştireceğiz. Seçili iteminin indexini almak için DataGridView metodlarından olan SelectionChanged kullanıyoruz ve aşağıdaki kodlamayı yapıyoruz. 

private void dataGridView1_SelectionChanged(object sender, DataGridViewCellEventArgs e)
        {
            getIndex = "0";
            getIndex = dgvTeacher.CurrentRow.Cells[0].Value.ToString();
        }

   DataGridView üzerinde seçtiğimiz itemın indexini belirledikten sonra artık silme işlemi için gerekli kodlamayı yapabiliriz. Sil buttonunun DialogResult=OK yapalım ve Click metodunu aşağıdaki gibi düzenleyelim.

  private void btnSil_Click(object sender, EventArgs e)
        {
            int index = Convert.ToInt32(getIndex);
            var p = se.Teachers.Where(q => q.Tid == index);
            DialogResult dialog = MessageBox.Show("Silmek İstediğinize Emin misiniz?","Öğretmen Sil", MessageBoxButtons.OKCancel);
           
            if (dialog == DialogResult.OK) 
            {
                p.ToList().ForEach(q => se.Teachers.Remove(q));
                se.SaveChanges();
            }

        }

   Şimdi isterseniz Tid = 5 olan "Cihan Kaleli" öğretmenini silelim.

Figür 4: Silme İşlemi

   OK tuşuna bastığımız zaman ekran görüntüsü aşağıdaki gibi olması beklenir.

Figür 5: Silme İşlemi Sonu

   Bu hafta LinQ teknolojisinden faydalanarak bazı veritabanı işlemleri gerçekleştirdik. Umarım faydalı bir yazı olmuştur. Gelecek hafta görüşmek dileğiyle...

   Referanslar:

11 Nisan 2014 Cuma

LinQ Nedir?


   Merhaba arkadaşlar,

   Geçen hafta beraber Entity Framework kullanarak temel veritabanı işlemleri nasıl yapıldığını incelemiştik. Bu hafta ise geçen haftalarda değindiğimiz konulardan olan LinQ teknolojisinden bahsedeceğim. Öncelikle LinQ'nin geçmişinden bahsetmek istiyorum.

   LinQ (Language Integrated Query) Türkçe karşılığı ile "Dil ile Bütünleştirilmiş Sorgu"dur. .Net Framework 3.5 ve Visual Studio 2008 ile birlikte piyasaya çıkmış,  bir çok alanda kolaylık ve yenilik sağlamıştır. Sağladığı kolaylıkların başında şüphesiz veriye kolay erişim imkanı ve SQL benzeri tek bir söz dizimi ile farklı tiplerdeki verilerin sorgulanmasını sağlamasıdır. Ayrıca C# ile sorgu yazmak, tip güvenli çalışma, ifadelerin otomatik olarak tamamlanması ve IntelliSense gibi özelliklerle geliştiricinin üretkenliğini artırmayı  da sağlar.
   
   LinQ'yi teknolojisine ait sınıflar ve methodları kullanmak istersek System.Linq kütüphanesini kullanmamız gerekir. Bu kütüphanenin tamamını buradan inceleyebiliriz.

   LinQ teknolojisinin bir çok farklı kullanım alanları bulunmakta. Bunlardan bahsedecek olursak;
  • LINQ to Objects: Bellek üzerindeki nesnelerden oluşan koleksiyonları sorgulamak için kullanılır.  
  • LINQ to SQL: SQL Server veritabanlarındaki tabloları sorgulamak için kullanılır. 
  • LINQ to DataSets :ADO.NET DataSet tiplerini sorgulamak için kullanılır.
  • LINQ to XML: Xml verilerini sorgulamak için kullanılır.
  • LINQ to Entity: ADO.NET Entity Framework tarafından oluşturulan varlıkları sorgulamak için kullanılır.
   LinQ geçmişini ve kullanıldığı alanlara göz attıktan sonra bu kavrama biraz daha aşina olduk. Şimdi isterseniz birazda yapısını inceleyelim.

Figür 1: LinQ Yapısı

   Yukarıdaki şekil LinQ yapısının şematik gösterimidir. Dilerseniz bir örnek üzerinden de yapısını ve kullanım şeklini anlatmaya çalışıyım.

   Elimizde bir öğrenci listesi olsun ve bu liste öğrencilerin ismini ve bölümünü içersin;
      
   List<Ogrenci> ogrenciler = new List<Ogrenci>
        {
                      new Ogrenci{ Adi = "Hürkan", Bolum = "Bil. Muh." },
                      new Ogrenci{ Adi = "Orhan", Bolum = "İşletme" },
                      new Ogrenci{ Adi = "Vedat", Bolum = "İstatistik"
                      new Ogrenci{ Adi = "Murtaza", Bolum = "Bil. Muh."  }
       }; 



   Biz bu listeden bölümü Bil. Muh. olan öğrencileri çekmek istediğimizde for , while , swich-case gibi döngüleri kullanabiliriz. Fakat bu döngüler biraz uğraş gerektirdiği  gibi aynı zamanda karmaşıkta olabilirler. Bu gibi durumlarda LinQ imdadımıza yetişiyor.  

   var birOgrenci = (from ogrenci in ogrenciler
                          where ogrenci.Adi == "Hürkan"
                          select ogrenci);

   Yukarıdaki sorguda Hürkan isimli öğrenci tipinde tek bir değişken dönecektir. LinQ teknolojisi sayesinde istersek bir dizi veya bir liste tipinde de değişken döndürmek mümkün. Bunun için bölümü Bil. Muh. olan öğrencileri döndürelim.

   var bilMuhOgrencileri = 
       (from ogrenci in ogrenciler
       where ogrenci.Bolum == "Bil. Muh."select ogrenci).ToList();

   Bu sorguda sonucunda ise bölümü Bil. Muh. olan bir liste elde etmiş olacağız.

   Bu örneğimizi ilk gördüğümüzde sormamız gereken ilk soru bir List <> yapısında "where, select, from" gibi metotların nasıl kullandık? olmalıdır. Bu metotları kullanmamızı sağlayan System.Linq kütüphanesidir. Bu kütüphaneyi projemize import ettiğimiz zaman yukarıdaki linkte bulunan bütün LinQ metotları kullanabiliriz. 

   Şimdi gelelim ikinci sorumuz olan bu var tipi de nedir acaba? ya. Eğer biz var tipinde bir değişken tanımlarsak bunun anlamı ben değişkeni tanımlarken tipini belirtmek istemiyorum demektir. Konuyu örnek vererek açıklamak gerekirse;

   var a= 10//Bu tanımlamada a değerine 10 atanırken tipide int olarak belirlenir.
  
   Bugünkü yazımda LinQ mimarisinin geçmişinden sağladığı kolaylıklardan ve kullanımından bahsetmeye çalıştım. Umarım faydalı bir yazı olmuştur. Bir sonraki yazımda görüşmek üzere...

Referanslar
1- http://msdn.microsoft.com/en-us/library/vstudio/bb397926.aspx
2- http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
3- http://www.koddunyasi.net/makale_dokuman/sql/linq.pdf