• Anasayfa
  • Hakkımızda
  • Etkinlikler
  • Destek Verin
  • Site Haritası
  • Giriş Yap
  • Üye Ol
  • Facebook
  • Twitter
  • RSS
Yazılım Dilleri
  • Soru - Cevap
  • EĞİTİM SETİ
  • KATEGORİ
  • DUYURU
  • TEKNOLOJİ HABERLERİ

Son Sorular

  • 23.04.2016 00:55:33C programlama 2 oyun
  • 20.04.2016 16:34:41Local Database
  • 15.04.2016 14:26:15Fatura kayıt işlemi
  • 21.03.2016 01:55:30C# problem

Popüler Sorular

  • 27.05.2012 05:49:50Asp.Net ile Date time alana veri ekleyemiiyorum ?
  • 2.04.2012 00:45:18.exe uzantılı dosya için dijital imza nerde nasıl alınır.
  • 12.05.2012 08:44:49Acil Yardım
  • 27.05.2012 13:46:51veri tabanı bağlantısı
  • .Net Framework
  • 8085 Assembly
  • Active Directory
  • ADO.NET
  • Android
  • Apple IOS
  • Arduino
  • ASP.NET
  • ASP.NET MVC
  • Blackberry
  • C#.Net
  • C++
  • CCG Framework
  • CISCO
  • CSS
  • Diğer
  • Dreamweaver
  • Entity Framework
  • Exchange Server
  • Gömülü Sistemler
  • GSM Programlama
  • Güncel
  • Güvenlik
  • HTML5
  • Java
  • Javascript / JQuery
  • Jira
  • Kariyer ve İş Yaşamı
  • LINQ
  • LibreOffice
  • Linux
  • Matlab
  • Microsoft Dynamics CRM
  • Mobil Uygulama Geliştirme
  • MySQL
  • NoSQL
  • Oracle
  • OWIN
  • PFSense
  • PHP
  • Powershell
  • Python
  • Sanallastirma
  • SAP-ABAP
  • SCOM 2012
  • SEO
  • Sharepoint 2010
  • Sharepoint 2013
  • Silverlight
  • Sistem Analiz ve Tasarımı
  • SQL Server
  • Symantec
  • TFS
  • T-SQL
  • Ubuntu
  • VB.NET
  • Veritabanı Yönetim Sistemleri
  • Visual Studio
  • VMware
  • WCF
  • Web Hosting
  • Windows 8
  • Windows Azure
  • Windows Phone 7.1
  • Windows Phone 8
  • Windows Server
  • Wordpress
  • WPF
  • Xamarin
  • XNA
  • Yazılım Mühendisliği
  • Yöneylem Araştırması
  • ASP.NET MVC
  • Entity Framework
  • Javascript / JQuery
  • LINQ
  • PHP

Son Duyurular

IPhone 6 ve IPhone 6 Plus Teknik Özellikleri ve Fiyatı

IPhone 6 ve IPhone 6 Plus Teknik Özellikleri ve Fiyatı

DELL'in Yeni Projesi: USB Bilgisayar (Project Ophelia)

DELL'in Yeni Projesi: USB Bilgisayar (Project Ophelia)

Windows Phone Youtube Uygulaması Google ve Microsoft ile Yeniden Yapılıyor

Windows Phone Youtube Uygulaması Google ve Microsoft ile Yeniden Yapılıyor

Android ve Apple IOS Telefonlar için Blackberry Messenger (BBM)

Android ve Apple IOS Telefonlar için Blackberry Messenger (BBM)

Nokia Lumia 925 Teknik Özellikleri, Lumia 928 ve 920 ile Karşılaştırması

Nokia Lumia 925 Teknik Özellikleri, Lumia 928 ve 920 ile Karşılaştırması

LG Optimus G Pro Özellikleri ve Gözle Video Oynatma Teknolojisi

LG Optimus G Pro Özellikleri ve Gözle Video Oynatma Teknolojisi

Ado.Net Entity Framework' de Lazy ve Eager Loading

Bildiğiniz üzere uzun bir süre önce Microsoft, LINQ to SQL yerine Ado.Net Entity Framework ile ilerleme kararı aldı. Bu konu ile ilişkili olaraktan okuduğum hemem hemen bütün kitaplarda Ado.Net' in geleceğinde önemli bir yere sahip olan Ado.Net Entity Framework alt yapısının geliştiriciler tarafından asla ihmal edilmemesi gerektiğide sıkça vurgulanmakta. Peki günlüğüme konu olan mesele nedir?

01.01.2013

Yazar: Burak Selim Şenyurt (Google+)

Kategori: ADO.NET

5652

Merhaba Arkadaşlar,

Bildiğiniz üzere uzun bir süre önce Microsoft, LINQ to SQL yerine Ado.Net Entity Framework ile ilerleme kararı aldı. Bu konu ile ilişkili olaraktan okuduğum hemem hemen bütün kitaplarda Ado.Net' in geleceğinde önemli bir yere sahip olan Ado.Net Entity Framework alt yapısının geliştiriciler tarafından asla ihmal edilmemesi gerektiğide sıkça vurgulanmakta. Peki günlüğüme konu olan mesele nedir?

Aslında günlüğe yazmadan önce odaklandığım nokta, aralarında master-detail ilişki bulunan tablo verilerinin, LINQ to SQL tarafında nasıl yüklendiğinin incelenmesiydi. Dolayısıyla önce LINQ to SQL tarafındaki duruma bir göz atmakya yarar var. İşe öncelikle basit bir Console uygulamasında kobay nesnelerimizden Northwind veritabanını kullanarak başlayabiliriz. Burada Visual Studio 2008 üzerinde ve .Net Framework 3.5 tabanlı bir geliştirme yaptığımızı belirtelim. Söz konusu uygulamamızda kullanacağımız LINQ to SQL diagramının içeriği aşağıdaki gibi tasarlanabilir.

Örnekte Category ve Product tablolarına ait tipleri göz önüne almaktayız. Buna göre "Kategoriler ve bu kategorilerdeki toplam ürün sayılarını öğrenmek" gibi basit bir sonuç kümesi elde etmek istediğimizde aşağıdakine benzer program kodlarını ele alacağımız muhtemeldir.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BlogSample
{
    class Program
    {
        static void Main(string[] args)
        {
            using (NorthwindDataContext northContext = new NorthwindDataContext())
            {
                // northContext.Log = Console.Out; // İsterseniz SQL sorgularını Console çıktısından da takip edebilirsiniz.
               
                foreach (Category category in northContext.Categories)
                {
                    Console.WriteLine("Category Name :{0} ({1})", category.CategoryName, category.Products.Count);
                }
            }
        }
    }
}

Programın bu haliyele çıktısı aşağıdaki gibidir.

Aslında istediğimizi elde etmiş görünüyoruz. Cool

Gayet doğal olarak foreach döngüsü içerisinde bir kategoriye bağlı ürün sayıları bulunurken Count özelliğinden yararlanılmaktadır. Ancak bu durumda Lazy Loading adı verilen durum oluşmakta ve SQL tarafına bakıldığında oldukça fazla sorgunun çalıştığı görülmektedir. Öyleki yukarıdaki kod çıktısı SQL Profiler yardımıyla incelendiğinde ilk sırada aşağıdaki sorgunun çalıştığı görülür.

Görüldüğü üzere ilk olarak tüm kategoriler Select sorgusu ile çekilmektedir. Ancak iş bundan sonra biraz daha dikkate değer bir hal alır. Nitekim her kategoriye ait ürün sayıları Products özelliği üzerinden elde edilmek istenmektedir. Bu durumda SQL tarafında her bir kategori satırı için birer sorgu cümlesi daha çalıştırılır.

Bu bir kaç satırlık veri için önemli gözükmese de, büyük boyutlu veriler ile çalışıldığı durumlarda önemli performans kayıplarına neden olabilir. Bu nedenle istenirse Eager Loading isimli bir teknikten de yararlanılabilir. Tek yapılması gereken kod tarafına aşağıdaki değişiklikleri eklemektir.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;

namespace BlogSample
{
    class Program
    {
        static void Main(string[] args)
        {
            using (NorthwindDataContext northContext = new NorthwindDataContext())
            {
                // northContext.Log = Console.Out; // İsterseniz SQL sorgularını Console çıktısından da takip edebilirsiniz.
                DataLoadOptions loadOption = new DataLoadOptions();
                loadOption.LoadWith<Category>(c => c.Products);
                northContext.LoadOptions = loadOption;

                foreach (Category category in northContext.Categories)
                {
                    Console.WriteLine("Category Name :{0} ({1})", category.CategoryName, category.Products.Count);
                }
            }
        }
    }
}

Bu durumda da kod aynı sonuçları verir ve SQL tarafındaki çıktıya bakıldığına tek bir sorgunun çalıştırıldığı gözlemlenebilir.

Ancak en iyi performans için bu teknikler yerine Anonymous Type kullanılması çok daha doğrudur. Öyleki sorguda istenen sadece kategori adları ve o kategoriye bağlı ürünlerin toplam sayılarıdır. Oysa ki sorgu cümlelerine bakıldığında o anda gerekli olmayan tablo alanlarının da hesaba katıldığı görülmektedir. Dolayısıyla sorgunun sadece, CategoryName ve buna bağlı Product satırlarının toplam sayısını bulacak şekilde iyileştirilebilmesi gerekmektedir. Aslında burada LINQ sorgularının defered execution adı verilen "gerektiği yerde sorguyu gönder" sistemide önemlidir. Kısaca LINQ sorgusunun yazıldığı satırda değilde, ilk kullanıldığı yerde SQL cümlesinin gönderilmesinden bahsediyoruz. Lafı fazla uzatmadan kod tarafındaki değişikliklerimize bakalım.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;

namespace BlogSample
{
    class Program
    {
        static void Main(string[] args)
        {
            using (NorthwindDataContext northContext = new NorthwindDataContext())
            {
                var resultSet = from c in northContext.Categories
                                select new
                                {
                                    c.CategoryName,
                                    c.Products.Count
                                };
                foreach (var result in resultSet)
                {
                    Console.WriteLine("Category Name :{0} ({1})", result.CategoryName,result.Count.ToString());
                }
            }
        }
    }
}

Bu durumda SQL tarafına giden sorgunun aşağıdaki gibi olduğu görülebilir.

Dikkat edileceği üzere sadece istediğimiz alanlar sorguya dahil edilmiştir.

Derken rüyadan uyanırım ve birden aklıma artık Ado.Net Entity Framework konulu bir yazı yazacağım gelir.Embarassed

Bakalım o tararfa Lazy Loading, Eager Loading durumları nasıl ele alınabilir. Bu kez projede kullanacağımız tiplerin EDM(Entity Data Model) diagramındaki görüntüsü aşağıdaki gibidir. Aynen yukarıda örneklerde olduğu gibi Category ve Product tablolarını ele alıyor olacağız.

Şimdi ilk kod parçamızı geliştirelim.

using (NorthwindEntities entity = new NorthwindEntities())
            {
                foreach (var category in entity.Categories)
                {
                    Console.WriteLine("Category Name :{0}({1})",category.CategoryName,category.Products.Count);
                }
            }

SQL Profiler'a geçmeden önce uygulama çalıştırıldığında aşağıdaki sonuç ile karşılaşılır.

Dikkatli gözlerden, ürün sayılarının 0 olarak geldiği kaçmayacaktır. SQL Profiler aracı ile gönderilen sorguya bakıldığındaysa sadece kategorilerin çekildiği ancak ürün sayılarının bulunması ile ilişkili bir şey yapılmadığı gözlemlenebilir.

Aslında bu son derece doğaldır nitekim Ado.Net Entity Framework modelinde Lazy Loading' in bilinçli ve açık bir şekilde yapılması istenmektedir. Dolayısıyla geliştiricinin gerçekten Lazy Loading yapmak istediğini kod tarafında belirtmesi gerekir. Peki bu nasıl yapılır? Aşağıdaki basit kod parçasında olduğu gibi...

using (NorthwindEntities entity = new NorthwindEntities())
            {
                foreach (var category in entity.Categories)
                {
                    if(!category.Products.IsLoaded)
                        category.Products.Load();
                    Console.WriteLine("Category Name :{0}({1})",category.CategoryName,category.Products.Count);
                }
            }

SQL Profiler' a bakıldığında aşağıdaki çıktı ile karşılaşılır.

İlk olarak kateogoriler çekilmiş sonrasında ilk 5 kategori için sırasıyla ürünlere ait sorgular çalıştırılmıştır. Ardından ise Category tablosu için yine bir Select çalıştırılmakta ve kalan 3 kategorinin her biri için tekrardan ürün sorguları yürütülmektedir.(Bu yazıda anlattıklarımı bire bir uygulamanızı, SQL Profiler aracaı yardımıylada irdelemeye çalışmanızı şiddetle öneririm.) 

Buradaki kod parçasında her bir kategori için buna bağlı ürünlerinde Products özelliği ile işaret edilen referansa yüklenmesi istendiği Load metodu yardımıyla belirtilmektedir. Bu kod ile Lazy Loading gerçekleştirilmiş olmaktadır. Peki ya Eager Loading? Eager Loading için aşağıdaki kod parçasını kullanmak yeterli olacaktır.

using (NorthwindEntities entity = new NorthwindEntities())
            {
                foreach (var category in entity.Categories.Include("Products"))
                {                   
                    Console.WriteLine("Category Name :{0}({1})",category.CategoryName,category.Products.Count);
                }
            }

Aslında tek yaptığımız Categories özelliği üzerinden Include metodunu çağırmak ve Products değerini vermek olmuştur. Buna göre SQL tarafında aşağıdaki sorgunun çalıştırıldığı görülür.

Elbette yine istediğimizi alamadık. Nitekim sadece kategori adı ve ürün sayılarını elde etmek gibi bir amacımız vardı. LINQ to SQL tarafında yapmış olduğumuz iyileştirmeyi Ado.Net Entity Framework tarafında da Include metodunu hesaba katarak ve yine Anonymous Type kullanarak gerçekleştirebiliriz.

using (NorthwindEntities entity = new NorthwindEntities())
            {
                var resultSet = from c in entity.Categories.Include("Products")
                                select new
                                {
                                    c.CategoryName,
                                    c.Products.Count
                                };
                foreach (var result in resultSet)
                {
                    Console.WriteLine("Category Name :{0}({1})", result.CategoryName, result.Count);
                }              
            }

Sonuç olarak SQL tarafına aşağıdaki sorgu cümlesi gönderilecektir.

Görüdüğü üzere sadece CategoryName ve sub query ile birlikte ürün sayıları hesaba katılmaktadır.

Böylece geldik bir günlük yazımızın daha sonuna. Bu yazımızda LINQ to SQL ve Ado.Net Entity Framework tarafında Lazy ve Eager Loading kavramlarını değerlendirmeye çalıştık. Umarım yararlı olmuştur.

Görüşmek dileğiyle...

Yazar Hakkında

Burak Selim Şenyurt

Burak Selim Şenyurt

buraksenyurt.com

Yıldız Teknik Üniversitesi Matematik Mühendisliği mezunu olan Şenyurt, 1999 yılında profesyonel olarak adım attığı yazılım dünyasında, 2003 yılından beri Microsoft .Net teknolojileri ile ilgilenmektedir. Yazılım hayatına Assist Line isimli Call Center firmasında Delphi programcısı olarak başlayan Şenyurt sonrasında, sırasıyla Bizitek(Junior Developer), Netron(Master Trainer), Citibank(Outsource Senior Software Developer), Innova(Application Development Consultant), ve TCM(Software Architect) firmalarında görev almıştır. Su anda ING Bank bünyesinde Kıdemli Yazılım Danışmanı olarak görev yapmaktadir. 2006, 2007 yıllarında C#, 2008,2009,2010 yıllarında ise Connected System Developer kategorisinde Microsoft MVP seçilen Şenyurt, evli ve 1 çocuk babasıdır. C# diline olan düşkünlüğü, oğluna S(h)arp adının verilmesinde önemli bir etken olmustur.

Sosyal Medya

ORANLAR

  • 5652izleme

Arkadaşlarınla Paylaş

  • Tweet

0 Yorum

Yorum Yaz / Soru Sor

Lütfen yorum yazmak veya soru sormak için üye girişi yapınız.

Son Yorumlar

  • Hocam Link başka sayfaya yönlendiriyor.
  • merhaba benim merak ettiğim bir konu var y...
  • Merhaba download linki çalışmıyor. Rica et...
  • Nevzat Bey selamlar, Açıkçası bizler a...
  • Parametreleri Cache İşleminden Yalıtma kon...

En Güncel Sorular

  • Bilgilendirme maili (C#.Net)
  • Power Pivot (Sharepoint 2010)
  • BigInteger, BigDecimal (Asp.Net ve Asp.Net MVC)
  • visual C# ile asp nette veritabanı islemleri (Asp.Net ve Asp.Net MVC)
  • Share Point ile Dosya Arşiv Yönetim Sistemi yapılabilir mi ? (Sharepoint 2010)

En Son Cevap Verilen Sorular

  • Bilgilendirme maili
  • BigInteger, BigDecimal
  • visual C# ile asp nette veritabanı islemleri
  • Share Point ile Dosya Arşiv Yönetim Sistemi yapılabilir mi ?
  • txt dosyasına veri yazma

Twitter

Takip et: @yazilim_dilleri

En Çok Okunanlar

Elif BAYRAKDAR

C# ile SQL Server Bağlantısı, Insert, Update ve Delete Sorguları

23.05.2013

  • 120031
  • 0
Hakan Keskin

C# ile Windows Service Projesi Oluşturma, Debug Etme ve Setup Hazırlama

17.12.2013

  • 65116
  • 0
batuhan avlayan

Php - Mail Gönderme (İletişim Formu)

02.09.2013

  • 48278
  • 0

Sponsorlar

KODLAB
Pluralsight
Exchange server is
Office 365
YAZILIM DİLLERİ
Yukarı Çık
  • Hakkımızda
  • Facebook
  • Twitter
  • RSS

© Yazılım Dillerinin Buluşma Noktası | Kaynak belirtildiği sürece makaleler kopyalanabilir.
YazilimDilleri.Net sitesinde yer alan kullanıcıların oluşturduğu tüm içeriklerin yayınlanması ile ilgili yasal yükümlülükler içeriği oluşturan kullanıcıya aittir, YazilimDilleri.Net hiçbir şekilde sorumlu değildir.

Kapat

Giriş Yap

Kullanıcı Adı

Şifre

Şifremi Unuttum

KULLANICI GİRİŞİ