25 Mayıs 2014 Pazar

POCO (Plain Old CLR Objects)


   Merhaba arkadaşlar,

   Bu hafta birlikte POCO objeleri hakkında çalışma yapacağız. POCO objeleri üzerindeki çalışmalarımızı gerçekleştirirken izleyeceğimiz yol şu şekilde olacak;
  • POCO objelerini açıklama
  • POCO objelerini oluşturma
  • POCO objeleri ile CRUD işlemleri
   *POCO Objelerini Açıklama

   Entity Framework, ADO.NET Data Model'da yer alan varlıklarımız(entity) için kendi sınıflarımızı yazabilmemize destek verir. Bu yapıda, varlıklar herhangi bir sınıftan türetilmez, herhangi bir interface'i implemente etmez, veri en sade şekilde tutulur. Böylece projemizi otomatik olarak oluşturulan modelle birlikte gelen birçok koddan kurtarıp, daha basit bir model oluşmasını sağlayabiliriz.

   *POCO Objesi Oluşturma

   Her zaman yaptığımız gibi oluşturduğumuz projeye Entity Framework Data Model oluşturma işlemlerini gerçekleştiriyoruz. Bu haftaki yazımda Microsoft'un hazır veritabanlarından biri olan AdventureWork veritabanını kullanacağım. İlgili veritabanına uygun olarak modelimizi oluştururken table bölümünden sadece ProductCategory tablosunu seçelim ve model oluşturmayı bitirelim. daha sonra .edmx uzantılı pencereye sağ tıklayıp Property penceresinden Code Generation Strategy kısmını None yapalım. Bu işlemi POCO objesi oluşturmak için yapmamız şart. 

Figür 1- Code Generation Strategy

   Code Generation Strategy kısmını None yaptıktan sonra Designer.cs sınıfımızın görüntüsü aşağıdaki gibi olacaktır.

Figür 2-Designer.cs

   Veritabanımız üzerinde yapacağımızı işlemleri gerçekleştirmek için tabloyla aynı isimde olan bir sınıf oluşturmamız gerekiyor. ProductCategory tablosu üzerinde çalışacağımız için ProductCategory isminde bir sınıf oluşturuyoruz ve bu sınıfımıza tablonun attributeleriyle aynı isimde olan propertyleri tanımlıyoruz.

Figür 3-ProductCategory Sınıfı

   Bu işlemi de tamamladıktan sonra Context tanımlaması yapabiliriz. Entity Framework ile otomatik oluşturulan Context, ObjectContext sınıfından kalıtılır. Bunu, bir EF oluşturduğunuzda Designer.cs'ine bakarak da görebilirsiniz.



   İlk önce yukarıdaki using kısmını projemize ekledikten sonra Program:objectContext kısmını kullanabiliriz. Program sınıfımızda, ProductCategory sınıfımızı barındıran ObjectSet tipinden bir özelliğimizin olması gerekiyor. Bunu sağlamak için de, aşağıdaki tanımlamaları  yapıyoruz.

Figür 4-Object Set

   CreateObjectSet() metodu ile yaptığımız örnekleme işlemini Context'imizin Constructor'ında da yapabiliriz. Şu an, sadece tek bir tablo üzerinde çalışıyoruz. O yüzden, bu işlemi Constructor'da yapmak performans ve bellek kullanımı konusunda sorun olmaz ama gerçek hayatta modellerimiz birçok tablodan oluşacak ve bu durumda Constructor'da gereksiz yere yaptığımız örnekleme, çok da optimum bir işlem olmayacaktır. Bu nedenle, en makul yöntem ObjectSet'imizi ihtiyaç duyduğumuzda oluşturmak.

   Bu aşamada, Context'imiz hala hangi bağlantı cümleciğini kullandığını bilmiyor. O nedenle Constructor'da bunu bildirmemiz gerekiyor.

Figür 5- Constructor

   Buradaki ilk parametre entity data modelimizi oluştururken App.Config dosyasına kaydettiğimiz bağlantı cümlesi(ConnectionString)nin adı, ikinci parametre ise Entity Container'ın adı(). Bu adı, Model'e sağ tıklayıp Model Browser dediğimizde açılan pencereden, AdventureWorksModel'ın altındaki EntityContainer'dan öğrenebilirsiniz.

   *POCO CRUD İşlemleri

   POCO objeleri kullanarak CRUD işlemleri yapmak çok basit. İsterseniz Create işleminden başlayabiliriz.

   Kayıt Ekleme

Figür 6-Ekleme

   Dikkat edecek olursak ctx.ProductCategory aslında bizim ObjectSet özelliğimiz. Burada SaveChanges() metodunu çağırmadığımız sürece veritabanı yapılan değişiklikden haberdar olmaz.

   Kayıt Güncelleme

Figür 7-Kayıt Güncelleme

   Context'teki ProductCategory sınıfımızın Model'deki hangi tabloya karşılık geldiğini bulmak için Context sınıfına bir metot yazılabilir ve ya ProductCategory sınıfımızda public const string EntitySetName="ProductCategory" şeklinde tanımlamada yapılabilir. Eğer bir metot yazmak istersek aşağıdaki gibi olmalıdır.
.

   public EntitySetBase GetEntitySet(Object entityType)
{
EntityContainer container = this.MetadataWorkspace.GetEntityContainer(this.DefaultContainerName,DataSpace.CSpace);
EntitySetBase entitySet = container.BaseEntitySets.SingleOrDefault(es => es.ElementType.Name == entityType.GetType().Name);           
return entitySet;
}

   Kayıt Silme

Figür 8-Kayıt Silme

   Öncelikle, sileceğimiz category nesnesini Context'imize ekliyoruz. DeleteObject() metodunu çağırdığımızda aslında silme işlemi gerçekleşmiyor; sadece nesnemiz silinecek olarak işaretleniyor, SaveChanges() dediğimizde siliniyor.

   Kayıt Getirme

Figür 9-Kayıt Listeleme

   Listeleme işlemide yukarıdaki kod blogu gibi yapılabilir. ProductCategory tipinde bir liste oluşturuyoruz. Daha sonra bu listeye bütün ProductCategory değerlerini yazıp listemizi döndürüyoruz. 

   POCO objelerini kullanarak CRUD işlemlerini açıkladıktan sonra bu haftaki yazımın sonuna geliyorum. Faydalı bir yazı olmuştur umarım. Bir sonraki hafta bu zamana kadar yapılan işlemlerin değerlendirmesini yapmak için tekrar burda olacağım. Görüşmek üzere...

11 Mayıs 2014 Pazar

Entity Framework ile Stored Procedure


   Merhaba arkadaşlar,

   Geçen haftaki konumuz olan Entity Framework Kalıtım ile birlikte  Entity Framework'e ait advance konu başlıklarından bahsetmeye başlamıştık. Bu hafta ise hem Entity Framework konuları arasında hemde Sql işlemlerinde önemli rol oynayan Stored Procedure konusundan bahsetmeye çalışacağım.

   Stored Procedure nedir? Hangi zamanlarda kullanılır? İsterseniz ilk önce bu soruları cevaplayarak bu haftaki konumuza başlayalım. Stored Procedure Türkçe karşılığı ile Saklı Yordam veya Saklı Prosedür olarak karşımıza çıkar. Genellikle büyük projelerde kullanılması gereken performans açısından büyük faydaya sahip bir T-Sql ifadesidir. Performans artışını nasıl sağlıyor peki? Stored Procedure veritabanımızda tutulan ve bir kez execute edildikten sonra bir daha execute işlemine gerek kalmadan yani tekrar veritabanı sorgusu yapmaksızın istenilen bilgileri  getirebilen ifadelerdir. Bu cümleden de anlaşılabileceği gibi bir uygulama katmanı değil veritabanı katmanı ifadeleridirler. Stored Procedurler ne zaman kullanılmalıdırlar? Yazımızın başında belirtiğim gibi genellikle büyük çaplı projelerde performans artışını sağlamak amacıyla kullanılırlar. Büyük bir veritabanına sahip bir proje düşünelim. Uygulama katmanında veritabanında aynı Sql sorgusunu birden fazla kullandığımızı varsayalım. Her ne kadar daha önce kullanılmış bir sorgu olsa bile bu Sql sorguları tekrar  kullanmak istediğimizde tekrar veritabanına gidip aynı cevabı döndürecektir. Oysa Stored Procedure veritabanı serverlarında tutulduğu için hem çok hızlı çalışacaktır hemde bir kere kullanıldıktan sonra tekrar veritabanından sorgu yapmaksızın bir sonuç verecektir. Ayrıca Stored Procedurelar parametre alabildikleri için benzer sorgular içinde kullanılabilirler. Buradan da anlaşılabileceği gibi hızın çok önemli olduğu büyük projelerde kullanılması tercih edilir.

   Stored Procedure Entity Framework ile nasıl kullanılır şimdide bundan bahsedelim isterseniz. Veritabanımız geçen haftalarda kullandığımız NorthWind olacak. Entity Framework ile birlikte kullanmak için bir Stored Procedure yazmamız gerekecek. Bunun için MS Sql 2008' i açıyoruz. NorthWind veritabanını import ediyoruz ve Stored Procedure yazmaya başlıyoruz.


   Yukarıdaki Sql Queryi yazıyoruz. Yazıdığımız Stored Procedure parametre olarak bir id alıyor. Daha sonra dışarıdan aldığımız integer tipindeki bu id ile [Products] tablosundaki CategoryID'ye eşit olan ürünlerin ProductID, ProductName attributelerini alıyoruz. Ayrıca Suppliers tablosu ile Join yaparak da Suppliers tablosuna ait olan Country özelliğini kullanıyoruz. Tabi ki bunun içinde Products tablosundan seçtiğimiz ürünlerin SupplierIDleri ile Suppliers tablosundaki Join yaptığımız sağlayıcılara ait SupplierIDleri eşit olması gerekiyor. Bu eşitliği de yaptıktan sonra artık Stored Proceduremiz hazır. Testini yapmak için Stored Proceduremize id olarak 2  atarak çalıştırıyoruz. Çıkan sonuç yukarıdaki gibi olacaktır.

   Stored Procedure yazımını tamamladıktan sonra şimdi Visual Studio kullanarak yapacağımız işlemlere başlayabiliriz. Data model oluşturma işlemininde bu zamana kadar hep Tables kısmını seçerek tamamlıyorduk. Fakat bu sefer Stored Procedure kullanacağımız için Stored Procedure seçeneğini de seçmeyi unutmuyoruz.

Figür 2-VisualStudio Data Model Oluşturma

   Yukarıdaki gibi Stored Procedure seçeneğini seçtikten sonra artık kodlama işlemine başlayabiliriz. İlk önce Sql 2008 de yaptığımız listeleme işlemini Entity Framework kullanarak nasıl yapılacağına bakalım. Listele adında bir method oluşturalım. Stored Procedure oluşturur iken hatırlarsanız integer tipinde bir id alıyordu. Bizim methodunumuzda integer tipinde bir değişken alsın. Methodumuza gönderdiğimiz bu id değişkenine göre bizim methodumuzda bu değişkeni Stored Proceduremize göndersin ve ilgili sonuçlar dönsün.

Figür 3 -Listele Methodu

   Listele methodunu yukarıdaki gibi yazıyoruz. Bu kodda ObjectResult tipinde MevcutUrunler listesi oluşturuyoruz. Bunu yaparken tabi ki daha önceden yazdığımızı Stored Proceduremizi kullanıyoruz. ObjectResult tipinde oluşturduğumuz listenin içine UrunleriGetir Stord Procedure sonucunda dönene tüm ürünleri atıyoruz. Methodumuzu çağırırken id değişkenini 2 olarak atadığımız zaman ekran çıktısı aşağıdaki gibi olması beklenir.

Figür 4-Listele Methodu id=2 Ekran Çıktısı

   Peki listeleme işlemi dışında başla işlemler yapabilir miyiz Stored Procedure üzerinde? Elbette yapabiliriz. Güncelleme silme ve ekleme işlemleri de yapılabilir. Eklemeyi göstermek için bir örnek yapalım. Yine aynı proje üzerinde eğer yeni bir ürünü Stored Proceduremize eklemek istersek aşağıdaki kodlama işlemini yapmamız gerekecektir.

Figür 5 -Ekle Methodu

   Yukarıda görülen ekle methodu asıl olarak bildiğimiz veritabanına ekleme işlemine benzemektedir. Fakat burada farklı olan kısım ise AddObject(proc) kısmıdır. Burada direkt olarak veritabanına ekleme değilde Stored Proceduremize ekleme yapmamızı sağlayan kısım AddObject()'dir.

   Stored Procedure kısmında ekleme ve listeleme işlemini anlattıktan sonra bu haftaki yazımın sonuna geliyorum. Umarım Stored Procedure hakkında ve Entity Frameworkteki kullanımında verdiğim bilgiler faydalı olmuştur. Bir sonraki yazımda görüşmek dileğiyle...

4 Mayıs 2014 Pazar

Entity Framework Kalıtım (Inheritance)


   Merhaba Arkadaşlar,

   Geçen hafta Lazy Loading konusunu işledikten sonra bu hafta daha fazla ilginizi çekeceğini düşündüğüm bir konu olan Entity Framework Kalıtım konusuna değineceğim. Entity Framework Kalıtım konusunu iki temel başlık altında inceleyebiliriz. Bunlardan ilki TPH yani Table-per-Hierarchy diğeri ise TPT yani Table-per-Type' dır.

   Table-per-Hierarchy Inheritance:
   TPH kalıtımı esasen bir tablo üzerinden yapılan kalıtımdır. Daha fazla açıklamak gerekirse veritabanımızda bir tablomuz var. Fakat bu tablo birden fazla Entity model tutuyor. İşte bu şekilde yapılan kalıtım TPH olarak adlandırılır.

   Table-per-Type Inheritance:
   TPT kalıtım ise TPH kalıtımın tam tersi desek pek de yanlış olmaz. Bunda ise veritabanımızda birden fazla one-to-one ilişki içerisinde bulunan tablo var fakat bu tabloların hepside tek bir Entity model şeklinde tutuluyor ise TPT olarak adlandırılır.

   Bu yazımda TPH kalıtımı yolunu nasıl projelerimizde kullanabileceğimizi anlatmaya çalışacağım. Her yazımda olduğu gibi bu yazımda da farklı bir veritabanı oluşturup, oluşturduğumuz bu veritabanını kullanarak işlemleri gerçekleştireceğim. İlk önce veritabanımızı oluşturmak için gerekli Sql Query'i yazalım. Aşağıdaki Query kullanarak sizde kendi veritabanınızı oluşturabilirsiniz.

create database EFInheritance

use EFInheritance

create table Users(
Id int NOT NULL IDENTITY(1,1),
Name varchar(50),
Email varchar(150),
primary key (Id),
)

create table Students(
Id int NOT NULL IDENTITY(1,1),
Major varchar(50),
primary key (Id),
)

create table Employees(
Id int NOT NULL IDENTITY(1,1),
Salary int,
primary key (Id),
)

create table PrintedDocument(
Id int NOT NULL IDENTITY(1,1),
Title varchar(50),
Subject varchar(50),
TypeCode int,
Author varchar(100),
Frequency varchar(50),
primary key(Id),
)

   Veritabanımızı oluşturduktan sonra yeni bir C# Console Application projesi oluşturuyoruz. Oluşturduğumuz projeye hazırladığımız veritabanının modelini ekliyoruz. Modelimizi ekledikten sonra aşağıdaki adımları sırasıyla uyguluyoruz.

   1- User Tablosu ile Student Tablosu Arasında Kalıtım Oluşturma
    User tablosu ile Student tablosu arasında inheritance oluşturmak için User tablosuna Sağ Tık -> Add New -> Inheritance... yi seçiyoruz.

Figür 1-Inheritance Ekleme
  
Karşımıza gelen ekrandan Select a base Entity kısmına User Select a derived kısmına Student seçiyoruz.

Figür 2-User Student Kalıtım

   2- User Tablosu ile Employee Tablosu Arasında Kalıtım Oluşturma
   1. adımda yaptığımız işlemi tekrarlıyoruz. Figür 2' de gösterilen işlemi Employee tablosu için de uyguluyoruz. 
Figür 3- Employee User Kalıtım

   3-Yeni Entity Oluşturup PrintedDocument Tablosuna Bağlama
   Yukarıdaki adımları tamamladıktan sonra PrintedDocument tablosuna bağlamak üzere iki farklı Entity oluşturacağız. Bunun için ilk önce bulunduğumuz sayfaya Sağ Tık -> Add New -> Entity... seçeneğini seçiyoruz.

Figür 4- Entity Ekleme
      Daha sonra karşımıza aşağıdaki gibi bir pencere açılacaktır. Açılan pencerede Entity name kısmına Book Base type kısmını ise PrintedDocument olarak seçip işlemi tamamlıyoruz.

Figür 5- Book Entity Ekleme

   4- Journal Entity Oluşturup PrintedDocument'e Bağlama
   Yukarıdaki basamakta gerçekleştirdiğimiz işlemleri bu adımda da yineliyoruz. Karşımıza çıkan pencereyi aşağıdaki ekran görüntüsü gibi dolduruyoruz.

Figür 6- Journal Entity Oluşturma
   5-Oluşturulan Entitylerin Mapping Tablosunu Düzenleme
   Oluşturduğumuz Entitylerin Mapping Tablosunu düzenlemek için herhangi bir Entity'e Sağ Tık-> Table Mapping seçeneğini seçiyoruz.

Figür 7-Table Mapping

   6- Entitylerin Table Mapping Atamaları
   Sağ Tık-> Table Mapping seçeniğine tıkladıktan sonra Book için şu işlemleri yapmamız gerekecek. İlk olarak Map kısmında PrintedDocumen kısmını çekiyoruz. Daha sonra Condition kısmında ise TypeCode seçtikten sonra karşısına "1" yazıyoruz. 

Figür 8-Book Mapping 

   7-Journal Table Mapping Atamaları
   Yukarıdaki işlemleri Journal Entity içinde tekrarlıyoruz fakat bu sefer Condition kısmına "2" yazıyoruz.

Figür 9 -Journal Mapping
   8-PrintedDocument Property Düzenleme
   Entityleri PrintedDocument tablosuna bağladıktan sonra PrintedDocument'in Abstract propertysini True yapıyoruz.

Figür 10- Abstract True


   9-İşlemleri Onaylama (Validate)
   Yaptığımız tüm bu işlemleri onaylamak için Sağ Tık -> Validate seçeneğine tıklıyoruz.
   
   
Figür 11-Validate

   Data Modellerimizin son görüntüsü aşağıdaki gibi olması beklenir.
Figür 12- Son Görünüm

   Bütün bu işlemleri gerçekleştirdikten sonra artık CRUD işlemlerini gerçekleştirebiliriz.

   Yeni bir öğrenci oluşturmak için aşağıdaki kodu kullanabilirsiniz.

using (var ae= new EFInheritanceEntities()){

   //Create
   var student = new Student(){
       Name = "Hürkan Seyhan",
       Email = "hurkanseyhan@gmail.com",
       Major = "Computer Engineer",
   };
   ae.Users.AddObject(student);

}

   Görüldüğü gibi "Name" ve "Email" attributesini Student tablosunda olmadığı halde onu sanki Student tablosu attributesi gibi kullanabildik ve en sonunda da User tablosunada oluşturduğumuz bu student objesini ekleyebildik.

   Yeni bir employee eklemek istersek;

   //Create
   var employee = new Employee(){
       Name = Ahmet Hamdi",
       Email = "ahamdi@gmail.com",
       Salary = 3500,
   };
   ae.Users.AddObject(employee);

ae.SaveChanger(); // Yapılan değişiklikleri veritabanına bildirmek için.

   Eğer oluşturduğumuz Student'ı silmek istersek;

   var hurkan = ae.Users.ofType<Student>()
                .Single(o=>o.Name="Hurkan Seyhan")
 ae.Users.Delete(Object(hurkan));
 ae.SavaChanges();

   Bu kodda da User tablosu üzerinde bulunan tipi Student olan bir nesneyi nasıl sileceğimizi görmüş olduk.

   Bugünkü yazımı burada sonlandırıyorum. PrinterDocument tablosu ile işlemleri sonraki haftalarda anlatmaya çalışacağım. Umarım faydalı bir yazı olmuştur. 

   Takipte kalmanız dileğiyle...

   Referanslar