Makale Özeti

Code First kod merkezli geliştirme ortamı sağlamaktadır. Her hangi bir tool veya XML eşleştirme dosyasına gerek kalmaksınız geliştirme yapabilirsiniz. Veri modeli nesnelerinizi her hangi bir sınıftan türetmeden basit POCO sınıfları olarak yazabilirsiniz. Konfigurasyon yerine isimlendirme özelliklerini kullanarak POCO nesnelerinizi veri tabanı nesneleriniz ile eşleştirebilirsiniz. Serinin ilk yazısında EF Code First bu özelliklerin nasıl kullanıldığını inceledik. EF Code First ile varsayılan olarak gelen entity ve veri tabanı nesneleri arasında ki eşleştirme nasıl değiştirilir?

Makale

Code First kod merkezli geliştirme ortamı sağlamaktadır. Her hangi bir tool veya XML eşleştirme dosyasına gerek kalmaksınız geliştirme yapabilirsiniz. Veri modeli nesnelerinizi her hangi bir sınıftan türetmeden basit POCO sınıfları olarak yazabilirsiniz. Konfigurasyon yerine isimlendirme özelliklerini kullanarak POCO nesnelerinizi veri tabanı nesneleriniz ile eşleştirebilirsiniz. Serinin ilk yazısında EF Code First bu özelliklerin nasıl kullanıldığını inceledik.

Varsayılan entity-veri tabanı eşleşmesi nasıl değiştirilir? EF Code First ile varsayılan olarak gelen entity ve veri tabanı nesneleri arasında ki eşleştirme nasıl değiştirilir?

Seri boyunca takip ettiğimiz adres defteri uygulamamıza devam edip yukarıda ki sorularmızın cevabını arıyalım. Standart .NET tipleri olan POCO nesnelerimiz hatırlayalım.

 public  partial  class  Person  
 {
     public  int  PersonId  { get ; set ; }
     public  string  FullName  { get ; set ; }
     public  string  Company  { get ; set ; }
     public  DateTime ? BirthDay  { get ; set ; }
     public  bool  IsFemale  { get ; set ; }
     public  virtual  List <Adress > Adresses  { get ; set ; }
 }
 public  partial  class  Adress 
 {
     public  int  AdressId  { get ; set ; }
     public  string  AdressType  { get ; set ; }
     public  string  FullAdress  { get ; set ; }
     public  int  PersonId  { get ; set ; }
     public  virtual  Person  Person  { get ; set ; }
 }

Bu POCO nesnelerimiz ile veri tabanı eşleşmesini sağlayan DbContext sınıfmızıda hatırlayalım. AddressBook DbContext sınıfından türetilmişti ve Persons ve Adresses property’lerine sahipti.

 public  class  AdressBook  : DbContext 
 {
     public  DbSet <Person > Persons  { get ; set ; }
     public  DbSet <Adress > Adresses  { get ; set ; }
 }

Veri tabanı eşleşmeleri için Code First yaklaşımını kullandık. Bunun manası AdressBook sınıfında yer alan Persons ve Addresses bizim veri tabanımızda aynı isimde ki tablolarla eşleşecekdir. Her bir Persons ve Adresses sınıflarıdandaki her bir property’de Persons ve Adresses tablolarında ki kolonlar ile eşleşecekdir.

Ekstra her hangibir konfigurasyon veya kodlama gerekmeden veri tabanı tablolarımız oluşmaktadır. Veri tabanımızda oluşan veri yapımız aşağıdaki gibidir.

Örnek uygulamada SQL CE kullandım. Yukarıdaki veri yapısında görüldüğü gibi Entity Framework Code First varsayılan olarak entity nesnemize birebir benzeyen bir tablo yapısı oluştudu.

Veri Tabanı Eşleştirme

Entity Framework Code First ile gelen veri tabanı eşleştirmesini DbContext.OnModelCreating metodunu override ederek değiştirebilirsiniz.

 public  class  AdressBook  : DbContext 
 {
     public  DbSet <Person > Persons  { get ; set ; }
     public  DbSet <Adress > Adresses  { get ; set ; }
     protected  override  void  OnModelCreating ( ModelBuilder  modelBuilder)
     {
         // entity - tablo eşleşmesini değiştir 
     }
 }

OnModelCreating(modelBuilder) metodu veri tabanınız ilk defa oluşturulurken çağırılacakdır. OnModelCreating metotu ile veri tabanı nesnelerinizin nasıl oluşturulması gerektiğini söyleyebilirsiniz. Adım adım olabilecek senaryoları inceleyelim.

Tablo İsmini Değiştirme

Nasıl Persons tablosunun ismini aşağıdaki gibi tblPersons yaparız?

Persons tablosunu tlbPersons yapmak için gerekli olan OnModelCreating metodu içinde Entity sınıfmıza ToTable(name) metodu ile özelleştirilmiş bir tablo adı vermektir.

 public  class  AdressBook  : DbContext 
 {
     public  DbSet <Person > Persons  { get ; set ; }
     public  DbSet <Adress > Adresses  { get ; set ; }
     protected  override  void  OnModelCreating ( ModelBuilder  modelBuilder)
     {
         modelBuilder.Entity <Person >().ToTable ("tblPersons" );
     }
 }

Yukarıda ki kod bloğu tablo ismi vermek için kullanılan sezgisel/fluent kuralları devre dışı bırakır ve OnModelCreating metotu ile belirtilen yeni kuralları uygulayarak tablo isimlendirmesini yapılır.

Kolon İsimlerini Değiştirme

Nasıl aşağıdakii gibi tüm kolonlara "col" ön eki ekleyebiliriz?

Tüm kolonlarımıza “col” ön eki eklemek için OnModelCreating metodu içinde entity nesnemiz için yeni bir eşleştirme/mapping eklememiz gerekmektedir.

 public  class  AdressBook  : DbContext 
 {
 public  DbSet <Person > Persons  { get ; set ; }
 public  DbSet <Adress > Adresses  { get ; set ; }
 protected  override  void  OnModelCreating ( ModelBuilder  modelBuilder)
 {
     modelBuilder.Entity <Person >().ToTable ("tblPersons" );
     modelBuilder.Entity <Person >().Property (c => c.PersonId ).HasColumnName ("colId" );
     modelBuilder.Entity <Person >().Property (c => c.FullName ).HasColumnName ("colFullName" );
     modelBuilder.Entity <Person >().Property (c => c.Company ).HasColumnName ("colCompany" );
     modelBuilder.Entity <Person >().Property (c => c.BirthDay ).HasColumnName ("colBirthDay" );
     modelBuilder.Entity <Person >().Property (c => c.IsFemale ).HasColumnName ("colIsFemale" );
     modelBuilder.Entity <Adress >().ToTable ("tblAdresses" );
     modelBuilder.Entity <Adress >().Property (c => c.AdressId ).HasColumnName ("colId" );
     modelBuilder.Entity <Adress >().Property (c => c.FullAdress ).HasColumnName ("colFullAdress" );
     modelBuilder.Entity <Adress >().Property (c => c.PersonId ).HasColumnName ("colRefId" );
 }
 }

Yukarıdaki kod bloğunda mevcut kurallar yerine OnModelCreating(modelBuilder) içindeki kuralların işletilmesi sağlanmıştır . Böylelikle varsayılan eşleştirme kuralları override edilmektedir. Code First ile Ansi SQL kolon yapısında desteklenen tüm özellikleri yukarıdaki gibi kullanabilirsiniz. Daha ayrıntılı özellikleri buradan inceleyebilirsiniz.

Bir Çok Entity Bir Table

En sık karşılaşılan seneryolardan biriside uygulama içinde ki entity nesnemiz ile veri tabanında ki tablo yapılarımızın bire bir örtüşmemesidir. Normalizasyon kuralları gereği aynı tabloda yer alması gereken veriler, nesne güdümlü yazılım mimarisi içinde farklı sınıflarda yer alması gerekebilmektedir. Aşağıdaki veri yapısında Person tablosuna göze atalım.

Burada IsWorkWith, IsDrunkWith, MustTakeGift bilgisi gibi alanlar Person tablosunda yer alması istiyoruz. Çünkü bu veriler Person verisine niteleyen verilerdir. Fakat bu bilgi özelleşmiş bir bilgi olduğu için farklı bir entity içinde taşınması daha doğrudur.

 public  partial   class  Familiarity 
 {
     public  bool  IsWorkWith  { get ; set ; }
     public  bool  IsDrunkWith  { get ; set ; }
     public  bool  MustTakeGift  { get ; set ; }
 }
 public  partial  class  Person  
 {
     public  int  PersonId  { get ; set ; }
     public  string  FullName  { get ; set ; }
     public  string  Company  { get ; set ; }
     public  DateTime ? BirthDay  { get ; set ; }
     public  bool  IsFemale  { get ; set ; }
     public  Familiarity  Familiarity  { get ; set ; }
     public  virtual  List <Adress > Adresses  { get ; set ; }
 }

Yukarıda ki entity yapısı ve veri yapısını birbirine uyumlu hale getirmemiz gerekmektedir. İki yapıyı uyumlu hale getirmek için OnModelCreating() metodu içinde Person entity sınıfımızda yer alan Contact property’sinin bir başka entity sınıfı olmadığını Contact sınıfının bir ComplexType olduğunu belirtmemiz gerekmektedir.

 protected  override  void  OnModelCreating ( ModelBuilder  modelBuilder)
 {
     modelBuilder.ComplexType <Familiarity >();
     modelBuilder.ComplexType <Familiarity >().Property (c => c.MustTakeGift ).HasColumnName ("colMustTakeGift" );
     modelBuilder.ComplexType <Familiarity >().Property (c => c.IsDrunkWith ).HasColumnName ("colIsDrunkWith" );
     modelBuilder.ComplexType <Familiarity >().Property (c => c.IsWorkWith ).HasColumnName ("colIsWorkWith" );

Böylelikle Contact sınıfımız bir entity sınıfı olarak değilde yer aldığı entity nesnesinin alt sınıfı olarak işlem görecektir.

Sonuç

Entity Framework Code First veri erişimini kod merkezli güzel bir yöntem ile çözmektedir. Veri erişimi mekanizmasında yer alan değiştirme noktalarından müdahale ederek veri erişim yapısını kendinize göre özelleştirebilirsiniz. Bu yazıda OnModelCreating(modelBuilder) değiştirme noktasına müdahale ederek veri tabanı yapısını değiştilmesini inceledik. Tüm işlemlerin kodlama ile basitce yapılabilmesi fazladan konfigürasyon gereketirmemesi, doğrulama özelliklerinin önyüz uygulamalar tarafından desteklenemesi gibi özellikler Entity Framework ile uygulama yazmayı kolaylaştırmaktadır.

Emre Coşkun

http://www.emrecoskun.net/demo