• 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

Entity Framework–İki Entity Bir Table ile Lazy ve Eager Loading

Ne zaman Eager Loading ne zaman Lazy Loading yapmamız gerektiğine karar vermemizde yardımcı olucak örnek bir senaryoyu inceliyoruz.

28.11.2014

Yazar: Burak Selim Şenyurt (Google+)

Kategori: .Net Framework

6361

Yandaki görüntü 1988 yılında Mevlüt Dinç(nam-ı diğer Mev Dinc) tarafından kurulan Vivid Image firmasının geliştirdiği oyunlardan birisine ait. The First Samurai. Mev Dinc ülkemizin yetiştirdiği en önemli değerlerden birisidir. Kendisi ile NedirTv topluluğunda yapılmış güzel bir röportaj da bulunmaktadır. Pek çoğumuz onu, SOBEE firması ile de tanımıştır. Ben ise uzun zaman önce Microsoft’ un Darphane’ deki binasında katıldığım bir söyleşiden…

MVP olduğum o dönemlerde Microsoft Türkiye düzenlediği bir etkinlik ile onu karşımıza çıkartmıştı. Kendisini büyük bir keyifle dinlemiştik. Nasıl bu günlere geldiğinden, geliştirdiği oyunlardan, kurduğu SOBEE firması' nın projelerinden bahsetmişti. Hatta akılda kalan önemli ifadelerden birisi de, yeni geliştirmekte oldukları oyunlarda C++ yerine C# programlama dilini tercih etmeleriydi. (Sene 2007 olabilir) Ancak benim daha çok aklımda kalan tam olarak hatırlayamasam da aşağıda yazan ifadeleriydi.

Bir savaş oyununda binanın tamamını düşünmeye gerek yoktur. O an için sadece aktörlerin bulunduğu odayı düşünmek yeterlidir.

Şimdi nereden geldik bu sözlere. Geçtiğimiz günlerde Entity Framework üzerine bir takım araştırmalar yaparken Lazy ve Eager Loading işlemlerinin hangi noktalarda kullanılabileceğine dair bazı yararlı bilgiler edindim. Bununla birlikte bir senaryo gerçekten dikkatimi çekti.

Temel Gereksinim

Özellikle içerisinde CLOB veya BLOB benzeri alanlar barındıran tabloların Entity Frameworktarafındaki kullanımlarında network yükünü hafifletmek adına bir tablonun iki Entity ile ifade edilebilmesi düşünülebilir. Böyle bir durumda Lazy Loading’ i tablo içerisindeki alanlar bazında uygulama şansına sahip oluruz. Bu, özellikle LINQ(Language INtegrated Query) sorgularını işlettiğimiz yerlerde performans açısından faydalı bir iyileştirmedir. Kısacası bir tablonun kendi alanları içerisinde ilişki kurup bunu Entity seviyesinde ifade etmemiz gerekmektedir. Gelin basit bir örnek üzerinden ilerleyerek konuyu incelemeye çalışalım.

Console Application formundaki örnekte yazının yazıldığı tarih itibariyle Entity Framework 6.1.1 sürümü kullanılmıştır. Entity Framework, NuGet paket yönetim aracı ile projeye dahil edilebilir.

Model

Code First yaklaşımını baz alarak geliştireceğimiz örnekte ilk olarak aşağıdaki sınıf çizelgesinde(Class Diagram) yer alan tipleri inşa ederek işe başlayabiliriz. Temel olarak PDF,WMVgibi yüksek boyutlarda ve binary formatta ifade edilebilen veri içeriklerini taşıyacak bir SQLtablosunun iki farklı Entity ile ifade edildiğini söyleyebiliriz. (Ki bu sebepten DocumentContentisimli sınıf içerisinde yer alan Content ve FrontCover özellikleri byte[] tipinden tanımlanmışlardır)

using System.ComponentModel.DataAnnotations; 
using System.Data.Entity;

namespace HowTo_EFTable 
{ 
    public class CompanyBookContext 
        :DbContext 
    { 
        public DbSet<Document> Document { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder) 
        { 
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<Document>().ToTable("Documents"); 
            modelBuilder.Entity<DocumentContent>().ToTable("Documents");

            modelBuilder.Entity<Document>() 
                .HasRequired(c => c.Content) 
                .WithRequiredPrincipal(); 
        } 
    }

    public class Document 
    {   
        [Key] 
        public int DocumentID { get; set; } 
        public string Title { get; set; } 
        public int PageCount { get; set; } 
        public string Language { get; set; } 
        public string Genre { get; internal set; } 
        public string Publisher { get; set; } 
        public virtual DocumentContent Content { get; set; } 
        public string ISBN { get; internal set; } 
    }

    public class DocumentContent 
    { 
        [Key] 
        public int DocumentID { get; set; } 
        public byte[] Content { get; set; } 
        public byte[] FrontCover { get;set; } 
    } 
}

Pek tabi dikkat edilmesi gereken önemli noktalar bulunmaktadır. Söz gelimi Document ve aslında büyük boyutlu içerikleri barındıran DocumentContent sınıfları arasında bir ilişki vardır. Öyleki her ikisi de aslında aynı tabloyu işaret etmelidir. Bunun için her iki sınıfın DocumentID isimli özellikleriKey nitelikleri(attribute) ile işaretlenmiştir.

Entity tiplerinde Key niteliği kullanılmazsa kuvvetle muhtemel aşağıdaki gibi bir çalışma zamanı hatası alınacaktır.

Document tipi içerisinde yer alan Content isimli özellik aslında DocumentContent tipindedir ve birNavigation Property şeklinde düşünülebilinir.(Sanki iki farklı tablo arasında one-to-one Relation kuruyoruz gibi düşünebiliriz)

Çok doğal olarak Code First yaklaşımının kullanıldığı bu örnekte modelin inşası sırasında da bazı özel işlemler yapılması gerekmektedir. Nitekim veri tabanı üzerinde tek bir tablo olması planlanmaktadır ve model’in içinde yer alan iki Entity’ nin aslında aynı tabloyu işaret edeceği veri tabanı nesnelerinin üretimi sırasında söylenebilmelidir.

Bu işlem ezilen(Override) OnModelCreating metodu içerisinde yapılmaktadır. Dikkat edileceği üzere Document ve DocumentContent isimli Entity tiplerinin aynı tablo’ yu(ki örnekte Documents)işaret ettikleri belirtilmektedir.

Bu arada Config

Uygulamada SQL Server kullanılmaktadır. Bu nedenle config dosyası içerisindekiconnectionStrings elementi içeriği önemlidir. Hatırlanacağı üzere DbContext türevli sınıf adı ile aynı isimde bir connectionString elementinin bulunması gerekmektedir. Örnekte aşağıdaki bağlantı bilgisi kullanılmıştır.

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
  <configSections> 
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> 
  </configSections> 
  <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> 
  </startup> 
  <connectionStrings> 
    <add name="CompanyBookContext" connectionString="data source=.;database=Azon;integrated security=SSPI;" providerName="System.Data.SqlClient"/> 
  </connectionStrings> 
  <entityFramework> 
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework"> 
      <parameters> 
        <parameter value="v11.0" /> 
      </parameters> 
    </defaultConnectionFactory> 
    <providers> 
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> 
    </providers> 
  </entityFramework> 
</configuration>

Ana Uygulama Kodları

Örnekte temel olarak Lazy ve Eager Loading operasyonlarının özellikle SQL Script' ler bazında nasıl olduğu üzerinde durulmaktadır. Bu nedenle aşağıdaki anlamsız kod içeriği ele alınabilir. Bizim için önemli olan arka planda yürütülen SQL betikleridir.

Program.cs

using System; 
using System.IO; 
using System.Linq;

namespace HowTo_EFTable 
{ 
    class Program 
    { 
        static void Main(string[] args) 
        { 
            byte[] samplePDF = File.ReadAllBytes(@"c:\DomainDrivenDesignQuicklyOnline.pdf"); 
            byte[] sampleCover= File.ReadAllBytes(@"c:\SampleCover.png");

            using (CompanyBookContext context=new CompanyBookContext()) 
            { 
                context.Database.Log = Console.Write; // SQL Script' lerini izlemek için Log çıktısını Console olarak set ettik.

                Document someBook = new Document 
                { 
                    Language = "TR", 
                    ISBN="1234-3456-BOOK-1202", 
                    Title = "Domain Driven Design Quickly - Online Edition", 
                    Genre="Computer Books", 
                    PageCount = 348, 
                    Publisher="Your Best Publisher", 
                    Content = new DocumentContent 
                    { 
                        FrontCover =sampleCover, 
                        Content =samplePDF 
                    } 
                };

                context.Document.Add(someBook); 
                context.SaveChanges();

                #region Lazy Loading

                var dcmnt = (from d in context.Document 
                             where d.ISBN == "1234-3456-BOOK-1202" 
                             select d).FirstOrDefault(); 
                if (dcmnt != null) 
                { 
                    byte[] bookContent = dcmnt.Content.Content; 
                    Console.WriteLine(bookContent.Length.ToString()); // bookContent' i her hangibir şekilde kullanmassak ikinci Select işlemi gerçekleşmez. 
                }

                #endregion

                #region Eager Loading

                dcmnt = (from d in context.Document.Include("Content") 
                         where d.ISBN == "1234-3456-BOOK-1202" 
                         select d).FirstOrDefault(); 
                if (dcmnt != null) 
                { 
                    byte[] bookContent = dcmnt.Content.Content; 
                }

                #endregion 
            } 
        } 
    }    
}

Örnekte Document tipinden bir nesne örneği üretilmektedir. Dikkat edilmesi gereken noktaContent özelliğine de DocumentContent tipinden bir örneğin atanmış olmasıdır. Document nesne örneğinin DbSet’ e eklenmesi işlemi veri tabanı tarafından Documents isimli tabloya bir insertişlemi olarak algılanmaktadır.

Kodun sonraki kısmında ise oluşturulan Document içeriğinin tablodan iki farklı şekilde çekilme işlemi söz konusudur. İlkinde Lazy Loading tekniğinin uygulaması söz konusudur. Documentiçeriği çekilirken DocumentContent tipinin taşıyacağı alanlar ilk etapta alınmazlar. Ta ki Contentözelliği kodda kullanılana dek(byte[] array' in boyutunun Console penceresine yazıldığı yer)

Eager Loading tekniğinin uygulandığı durumda ise DocumentContent tipinin işaret ettiği Contentve FrontCover alanlarının, LINQ ifadesindeki Include terimi nedeniyle Select işlemi sırasında çekilmesi söz konusudur. Yani tüm tablo içeriği, Lazy Loading’ in aksine Select ifadesi ile birlikte gelmektedir.

Çalışma Zamanı Analizi

Aslında durumu daha iyi analiz etmek adına çalışma zamanı çıktılarına bakabiliriz. Log içeriğiniConsole penceresine yansıttığımızdan, arka planda çalıştırılan SQL Script' lerini kolayca görebiliriz.

Şimdi ilk LINQ ifadesini  ele alalım(Lazy Loading region’ lı kısım)

Arka planda ilk olarak Content ve FrontCover alanlarını içermeyen bir Select cümleciği çalıştırıldığı görülmektedir.

SELECT TOP(1)
[Extent1].[DocumentID] as [DocumentID],
[Extent1].[Title] as [Title],
[Extent1].[PageCount] as [PageCount],
[Extent1].[Language] as [Language],
[Extent1].[Genre] as [Genre],
[Extent1].[Publisher] as [Publisher],
[Extent1].[ISBN] as [ISBN]
FROM [dbo].[Documents] as [Extent1]
WHERE N'1234-3456-BOOK-1202'=[Extent1].[ISBN]

Bu son derece doğaldır nitekim gelmeyen alanlar kodun o anki satırına kadar talep edilmemiştir. Ancak elde edilen Document nesne örneğinin Content özelliği üzerinden hareketle uzunluk bilgisi ekrana yazılmak istendiğinde, SQL tarafında ikinci bir Select ifadesinin çalıştırıldığı görülmektedir.

SELECT TOP(1)
[Extent1].[DocumentID] as [DocumentID],
[Extent1].[Content] as [Content],
[Extent1].[FrontCover] as [FrontCover]
FROM [dbo].[Documents] as [Extent1]
WHERE [Extent1].[DocumentID]=@EntityKeyValue1

Aynı Where koşulu için çalıştırılan bu ifade de Documents tablosundan sadece FrontCover veContent alanlarının çekildiğine dikkat edilmelidir. İşte bu, “ihtiyaç duyduğum yerde verileri yükle”felsefesi olarak yorumlanabilir. Kısaca Lazy Loading…

Gelelim ikinci ifadeye; Bu kez LINQ sorgusunda Include metodunun çağırıldığı ve parametre olarakContent isimli Navigation Property değerinin verildiği görülmektedir. Buna göre Documentstablosundaki tüm alanlar(Document ve DocumentContent Entity tiplerine ait özelliklerin işaret ettikleri) Select cümleciğine dahil edilmiştir.

SELECT TOP(1)
[Extent1].[DocumentID] as [DocumentID],
[Extent1].[Title] as [Title],
[Extent1].[PageCount] as [PageCount],
[Extent1].[Language] as [Language],
[Extent1].[Genre] as [Genre],
[Extent1].[Publisher] as [Publisher],
[Extent1].[ISBN] as [ISBN],
[Extent1].[Content] as [Content],
[Extent1].[FrontCover] as [FrontCover]
FROM [dbo].[Documents] as [Extent1]
WHERE N'1234-3456-BOOK-1202'=[Extent1].[ISBN]

İşte bu da, “o an kullanmayacak olsam da tüm içeriği şu anda bana ver.” felsefesidir. Yani Eager Loading…

Tabi program çalıştırıldığında modelin inşasının sonuçlarına da bakılmalıdır. SQL Management Studio ile ilgili veritabanına gidilirse Documents isimli tek bir tablonun aşağıdaki şekildeki gibi oluşturulduğu görülebilir.

Ayrıca kod tarafında gerçekleştirilen Insert işlemi sonrasında, iki farklı Entity örneğindeki özellik değerlerinin tek bir satır içerisine yerleştirildiği fark edilebilir.

Sonuç

Aslında yazımızın başında da belirttiğimiz ve Mev Dinc’ in ifade ettiği üzere, bazen olay anında ve yerinde tüm detayın olmasına gerek yoktur. O anda sadece bulunması gereken verilere ihtiyaç vardır. Bu felsefe görüldüğü üzere sadece oyun programlama tekniklerinde değil farklı konularda da karşımıza çıkmaktadır.Tabi bu felsefe kurgunun çok iyi yapılmasını gerektirir. Lazy ve Eager Loading teknikleri, diğer ORM araçlarında olduğu gibi Entity Framework’ ün de olmassa olmazlarıdır. Makalemizde ele aldığımız konu ince bir performans ayarını işaret etmektedir. Bir tabloyu kod  tarafında parçalı şekilde ifade edebilmek, gerekli parçalarının Lazy Loading ile yüklenmesinin yolunu açmaktadır. Konu hakkında daha detaylı bilgiye Peter Vogel' in MSDN Magazine' de yayınlanan makalesinden ulaşabilirsiniz. 

Böylece geldik bir makalemizin daha sonuna. Bir bakşa makalemizde görüşünceye dek hepinize mutlu günler dilerim.

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

  • 6361izleme

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

  • 119832
  • 0
Hakan Keskin

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

17.12.2013

  • 64802
  • 0
batuhan avlayan

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

02.09.2013

  • 48159
  • 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İŞİ