Entity Framework İle Code First Yaklaşımı
Merhaba,
Linq To SQL gibi Entity Framework mimariside biz yazılımcılara oldukça hız kazandırmakta ve veritabanı işlemlerinde atılan bir çağın basamaklarını teşkil etmektedir. Haliyle biz yazılımcılar ister istemez bu mimarilere yönelmekte ve meraklarımızın yanında çalışmalarımızı da bu mimarilerle sürdükmekteyiz. Tabi günümüzde bir yapı yahut mimariye yönelirken kendimize uygun prensip ve yaklaşım seçmemiz yaşayacağımız karışıklığı ortadan kaldıracaktır. Burada demek istediğim o ki, günümüzde her mekanizmasının birden fazla yaklaşımı ve prensibi mevcut olduğundan, öğrenme sürecinde kaçınılmaz olarak kaynakların farklılıkları kafanızı karıştıracaktır. İşte bunun sebebi, her kaynağın farklı bir yaklaşımı merkez edinmesindendir.
Entity Framework mimarisinde temelde üç adet yaklaşım mevcuttur.
- Code First
- Database First
- Model First
Bu yazımızda Code First yaklaşımı üzerine duracağız. Zamanla diğer yaklaşımlar üzerinde de istişaremizi ederiz diye umuyorum.
Code First Nedir?
Veritabanı ile Programlama dili arasında bağ kuran bir tekniktir. Projenizde veritabanı işlemlerinizi mümkün mertebe Visual Studio tarafında kod yazarak gerçekleştirmenizi sağlayan bir yaklaşımdır. Bu yaklaşım sayesinde veritabanı arayüzü ile yazılımcı arasında ilişki minimize edilmektedir.
Code First yapısında programlama dilindeki “class” yapıları veritabanındaki “tablo” yapılarına, “property” yapıları ise veritabanındaki “kolon” yapılarına denk gelmektedir.
Ayrıca Attribute’lar sayesinde veritabanı yapılarına Validationlar uygulanabilmekte ve kolonlara belirli şartlar veyahut kısıtlamalar koyulabilmektedir.
En önemlisi ise projenizdeki modelin oto kontrolünü elinizde hissetmenize ve tam hakimiyetle istediğiniz gibi kullanmanıza olanak tanıyor. Database First yaklaşımı Linq To SQL yapısındaki gibi sürükle bırak mantığıyla çalışmakta ve herşeyi otomatik halletmektedir. Eee bir yazılımcının en büyük arzusu; tez işte tam hakimiyet… İşte Code First böyle bir çizgiye sahiptir.
Projeye Entegrasyonu ve Code First Yapısının İnşası
Öncelikle yapmamız gereken, üzerinde çalıştığımız projeye Entity Framework Nuget paketini eklemektir.
“Tools” -> “Nuget Package Manager” -> “Manage Nuget Packages for Solution…” kombinasyonunu takip edin.
Açılan pencerede aşağıdaki gibi “entity” anahtar kelimesini aratın. Listede karşınıza çıkan “EntityFramework” paketini Install ediniz.
Yüklemeyi gerçekleştirdikten sonra gerekli Entity Framework referansları projeye entegre edilmiş bulunmaktadır.
Şimdi sıra geldi Code First yapısıyla bir model oluşturmaya. Haliyle oluşturma aşamasında inşa sürecinide görmüş olacağız.
Hatırlarsanız eğer Code First yapısı veritabanı işlemlerini programatik olarak gerçekleştirmemize yarayan bir yaklaşım sergilemekteydi. O halde örnek olarak çalışacağımız projede hem veritabanı oluşturacağız, hem de Code First yapısının diğer nimetlerinden faydalanacağız.
Gelin tüm teferruatınca şu konuyu ele alalım…
Code First ile tüm modele hakimiyet sağlamanın ekstra getirisi kodlara disiplinli bir hiyerarşik düzen sağlamanın sorumluluğu getirmesidir. Haliyle modele tam hakimeyet demek, a’dan z’ye biz kodlayacağız demek. O yüzden entitylerimi(yani tabloları) “Entity” klasörüne, yazılım ile server arasında iletişimi sağlayacak olan Context sınıfını da “Context” klasörüne oluşturacağım.
Şimdi Code First ile bir veritabanı oluşturmayı ve bu veritabanı içerisine bir tablo eklemeyi görelim.
class OrnekTablo { public int ID { get; set; } public string Kolon1 { get; set; } public string Kolon2 { get; set; } }
Öncelikle tablomuzu temsil eden sınıfımı oluşturdum. Şimdi veritabanı ile bağlantı kuracağımız Context sınıfını oluşturuyorum.
class OrnekVeriDbContext : DbContext { public DbSet<OrnekTablo> OrnekTablos { get; set; } }
Context sınıfımızı incelerseniz eğer DbContext sınıfından türemektedir. Bunun sebebi, Entity Framework mimarisinin nimetlerine bu sınıfın mirasından erişebilecek, ayriyetten ilgili sınıfımızın bir Context sınıfı olmasını sağlayacaktır. “OrnekVeriDbContext” sınıfına verdiğimiz isim bizim için oldukça önemlidir.
Code First yapısında en temel nokta, veritabanındaki tablolaları temsil edecek Generic yapıdaki DbSet tipinden propertyler olarak tutmasıdır. Yukarıda gördüğünüz “OrnekTablos” isimli property, bizim “OrnekTablo” isimli tablomuzun, veritabanındaki fiziksel yansımasını oluşturacaktır.
İşte en temelde de olsa Code First yapısında bir veritabanı dizayn ettik ve sıra bu veritabanını oluşturmaya geldi. Peki… Oluşturduğumuz bu yapı, hangi Server’da hangi isimde veritabanı oluşturacağını biliyor mu? hayır…
İşte bu bildiriyi de eğer web kısmında çalışıyorsanız “web.config” dosyasında, yok eğer masaüstünde takılıyorsanız “app.config” dosyasında belirtebilirsiniz.
<?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" /> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> </startup> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework"> <parameters> <parameter value="mssqllocaldb" /> </parameters> </defaultConnectionFactory> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> </providers> </entityFramework> <connectionStrings> <add name="OrnekVeriDbContext" connectionString="Server=.;Database=OrnekVeritabani;Trusted_Connection=true;" providerName="System.Data.SqlClient"/> </connectionStrings> </configuration>
Yukarıdaki app.config dosyasına “connectionStrings” node’ı eklenerek gerekli ayarlama yapılmıştır. Tabi, sizlerin net görebilmesi benimde net izah edebilmem için ilgili parçayı aşağı almamız uygun olacaktır.
. . . <connectionStrings> <add name="OrnekVeriDbContext" connectionString="Server=.;Database=OrnekVeritabani;Trusted_Connection=true;" providerName="System.Data.SqlClient"/> </connectionStrings> . . .
Gördüğünüz gibi bir connectionStrings node’ı açıyor ve içerisine ekleme yapıyoruz. “name” özelliğine Context sınıfımızla birebir aynı ismi veriyoruz. Bunda zorunlu değiliz lakin başka Context’lere nazaran karışıklığı önlediği için tavsiye ediyorum. “connectionString” Attribute’una bildiğiniz Provider’ımızı yazıyoruz. Ama burada dikkat!!! Yazdığınız bu Provider’da ki veritabanı olmayan bir veritabanı olması gerekiyor. Olması gerekiyor ki, Code First yapısı kendisi oluşturabilsin. Bunların yanında “providerName” Attribute’u sayesinde ilgili bağlantının System.Data.SqlClient kütüphanesinde çalışacağını, yani SQL Server olduğunu belirtmiş oluyoruz.
Bu işlemlerden sonra Program.cs sınıfında “OrnekVeriDbContext” sınıfından bir nesne üretip ilk oluşumu seyredebiliriz.
class Program { static void Main(string[] args) { OrnekVeriDbContext Veri = new OrnekVeriDbContext(); Veri.Database.Create(); } }
Yukarıdaki kod bloğunu çalıştırdığımız zaman neler olmuş bakalım…
Anahh 🙂 Gördünüz mü, app.config dosyasında belirttiğim isimde bir veritabanı oluşturulmuş ve “OrnekTablo” isminde bir tablo eklenmiştir. Tabi oluşturma aşamasında Entity Framework mantığı işte “OrnekTablo” değil “OrnekTabloes” olarak çoğul maksatlı bir isimde eklenmiştir. Eee bunun niyeti, Linq To Sql’de olduğu gibi çoğul olanları belirleyebilmektir. Velhasıl sonraki yazılarımızda bu tarz tablo isimleri vs. gibi değerlere, tablo oluşum sürecinde müdahale edecek ve istediğimiz değişikliği uygulayabileceğiz.
Şimdi dikkatlerinizi oluşturulan tablonun kolonlarına çekmek istiyorum. Biz hiç bir işlem yapmadığımız halde nasıl oluyorda ID kolonu primary key olmuş oluyor? ve hatta identity özelliğine bakarsanız eğer birer birer arttığını bile görebilirsiniz.
Bunun sebebi; Code First yapısında, tablo olarak dizayn edilen sınıfta tanımlanmış ilk property otomatik olarak primary key görülüyor ve identity özelliği bire birden default atanıyor. O yüzden ilk propertynin ID olduğunu belirtecek bir isim vermeye dikkat etmenizi öneriyorum.
Şimdi bu bilgiyi unuttuk, ya da farklı bir isimde primary key kolon tanımlamak istiyorum diyorsanız aşağıdaki kod bloğunu inceleyiniz.
class OrnekTablo { public int hilmi { get; set; } public string Kolon1 { get; set; } public string Kolon2 { get; set; } }
Varsayalım, ilk propertymizin ismi “hilmi” olsaydı ne gibi bir durumla karşılaşırdık.
An unhandled exception of type ‘System.Data.Entity.ModelConfiguration.ModelValidationException’ occurred in EntityFramework.dll
Additional information: One or more validation errors were detected during model generation:
EFCodeFirst.Model.Context.OrnekTablo: : EntityType ‘OrnekTablo’ has no key defined. Define the key for this EntityType.
OrnekTablos: EntityType: EntitySet ‘OrnekTablos’ is based on type ‘OrnekTablo’ that has no keys defined.
Evet yukarıdaki gibi ilk propertymiz “hilmi” olsaydı bu hata mesajıyla karşılaşırdık. Hatta hata mesajının görselinide paylaşmak gerekirse buyurun.
Bu hatanın yegane sebebi, “hilmi” isminde bir kolonun primary olma ihtimalinin sıfır olmasıdır. Yani derleme aşamasında mimari bizden tablo ismiyle benzer ya da sadece id kolonu olduğunu belirten bir property istediğini belirtiyor.
Haliyle bizler tutturup illa ki “hilmi” kolonunun primary key olmasını istiyorsak eğer “Key” Attribute’unu ilgili propertye uygulamalıyız.
class OrnekTablo { [Key] public int hilmi { get; set; } public string Kolon1 { get; set; } public string Kolon2 { get; set; } }
Ekran görüntüsünde de gördüğünüz gibi “hilmi” isminde bir primary key kolon oluşturmuş olduk. Biliyorum çok gülünç 😀 😀
Uzun lafın kısası burada anlatmak istediğim, tablonuzun ismi “A” ise ilk propertyi “AId”, “AID” veyahut “ID” gibi isimler vermeniz Entity Framework Code First açısından kabul edilebilir bir durum olacaktır.
Code First İle Veri Ekleme / Silme / Güncelleme
Aslında Code First’e özel bir ekleme/silme veyahut güncelleme işlemi gerçekleştirmeyeceğiz. Şuana kadar yaptığımız işlemler neticesinde bir Entity Framework mimarisinde kullandığımız normal veri modifikasyonu metod ve yöntemlerini ele alacağız.
Yukarıdaki ekran görüntüsünde de gördüğünüz gibi “OrnekVeriDbContext” Context sınıfımız içerisinde DbSet
class Program { static void Main(string[] args) { OrnekVeriDbContext Veri = new OrnekVeriDbContext(); Veri.OrnekTablos.Add(new OrnekTablo { Kolon1 = "Örnek veri kolon1 1", Kolon2 = "Örnek veri kolon2 1" }); Veri.SaveChanges(); } }
Bu şekilde veri eklenebilmekte,
class Program { static void Main(string[] args) { OrnekVeriDbContext Veri = new OrnekVeriDbContext(); OrnekTablo ornek = Veri.OrnekTablos.FirstOrDefault(o => o.ID == 1); ornek.Kolon1 = "Örnek veri kolon1 güncel"; ornek.Kolon2 = "Örnek veri kolon2 güncel"; Veri.SaveChanges(); } }
bu şekilde veri güncellenebilmekte,
class Program { static void Main(string[] args) { OrnekVeriDbContext Veri = new OrnekVeriDbContext(); OrnekTablo ornek = Veri.OrnekTablos.FirstOrDefault(o => o.ID == 1); Veri.OrnekTablos.Remove(ornek); Veri.SaveChanges(); } }
bu şekilde veri silinebilmekte
ve
class Program { static void Main(string[] args) { OrnekVeriDbContext Veri = new OrnekVeriDbContext(); foreach (var item in Veri.OrnekTablos) { Console.WriteLine($"{item.Kolon1} {item.Kolon2}"); } Console.Read(); } }
bu şekilde verileri çekebiliyoruz.
Bu yazımızda Entity Framework Code First yapısına giriş yaparak, bir projeye entegrasyonun nasıl sağlanacağını, yapısal olarak nasıl bir çalışma sergilenmesi gerektiğini ve temel veritabanı işlemlerini incelemiş olduk.
Hemen bir sonraki yazıda Code First yöntemiyle tablolar arasında ilişkinin nasıl kurulacağını inceleyeceğiz.
Eee o halde sonraki yazımda görüşmek üzere…
İyi çalışmalar…
Gençay bey connectionstringde initial catalog kısmı sanırım unutulmuş. Ben de fark etmeden çalıştırdığımda 403 hatası aldım. Bilginize.
Güzel makalelerle bilgi veriyorsunuz. Sitenizi takip ediyorum, verdiğiniz değerli bilgiler için teşekkür ederim.
Pardon sanırım ben yanlış anlamışım. Database varmış zaten.
Teşekkür ederim Doğancan Bey.
Merhabalar
Benim söyle bir sıkıntım var.Bir tablonun key kısmını değiştirdiğimde aşağıdaki gibi hata veriyor.
Sizin yapmış oldugunuz örnegin aynısını yaptım. Fakat yine sonuc aynı. Siz örnekte dbyi silip tekrardanmı oluşturdunuz? Eğer silip tekradan oluşturduysanız sorumu su sekilde değiştirmem gerekiyor. Canlı sistemde buşekilde bir güncellemeye ihtiyacım olursa nasıl yapacagım?
One or more validation errors were detected during model generation:
Teşekkürler
Merhaba,
Sonraki makalelerde ele aldığım Migrations İşlemleri ile dbyi silip tekrar oluşturmadan güncellemelerimizi fiziksel yansıtabiliyoruz.
İlgili makale için tıklayın -> https://www.gencayyildiz.com/blog/entity-framework-code-first-migrations-islemleri/
Gerçekten süper bi site açıklamalarınız anlaşılır ve adım adım
Merhaba bununla Asp.net Core ile örnek bir makaleniz olacak mı ?
Merhaba,
Asp.NET Core 2 MVC’de Migrations İle Veritabanı İşlemleri başlıklı makaleme göz atabilirsiniz.
merhabalar 1 haftadır uğraşıyorum yetiştirmem gereken bir projem var ancak enable-migrations işleminde takılıyorum No context type was found in the assembly hatası alıyorum -verbose yaparak da denedim ancak sorunu çözemiyorum bir öneriniz var mıdır ? umarım vardır delirmek üzereyim zira
Merhaba,
şeklinde deneyip bana geri bildirimde bulunabilir misiniz?
Ilk defa bır blog sitesine yorum yazıyorum. Tebrikler güzel yazı olmuş.. Yeni başlayanlara göz korkutmadan anlatmaya çalışmışsınız. Tek sıkıntım türkçe karaktere uygun yazı tipi seçmeniz olabilir.
Kolay gelsin…
🙂 Türkçe karakter konusunda çok şikayet alldığımı bilmenizi isterim. Ama üşengeçliğin kabuğunu kıramıyorum 🙂
Güzel yorumun için teşekkürler.
İyi çalışmalar.
Merhaba proje çalıştığında, mssql veri değiştirdiğimde projeyi kapatıp açmadan değişiklik görünmüyor. ne yapabilirim.
Merhaba,
Aradığınız çözümü şuradaki makaleden inceleyebilirsiniz.
Teşekkürler hocam.
Kolay gelsin.
Gencay hocam hocam 11 tabloluk bir kütüphane otomasyonu yapıyorum 10 tablomda herhangi bir sorun çıkmadı.11.tablom adres tablosunda 3 ilişki mevcut 3 tablo ile bire çok ilişkisi var tek tabloyla bağlantı yaptığım zaman hata almıyorum.Ama diğer iki tabloyla bağlantı kurduğum zaman
System.Data.SqlClient.SqlException: ‘Introducing FOREIGN KEY constraint ‘FK_dbo.YayinEvleris_dbo.Adreslers_AdresID’ on table ‘YayinEvleris’ may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
hatasını alıyorum.
tablolarımda bunlar,