Asp.Net Mvc – Code First ile Veritabanı İşlemleri 1 – Proje Başlangıcı (Asp.Net Mvc Yazı Dizisi – 11)

 

Önceki Yazı : Asp.Net Mvc Razor View Engine Bölüm 3 (Asp.Net Mvc Yazı Dizisi – 10)

Merhaba Arkadaşlar,

Önceki yazılarımızda, Mvc sistemini genel olarak incelemiş, Layout, Partial View gibi konuları irdelemiş, Razor'u kapsamlı bir şekilde incelemiştik. 

Şimdi ise veritabanı konusunu, Entity Framework Code First üzerinden inceliyor olacağız.

Bundan sonra ki çalışmamızda, kapsamlı bir blog uygulaması geliştiriyor olacağız. 

Asp.Net Mvc uygulamalarında, klasik Ado.Net sistemini kullanabildiğimiz gibi, Linq to Sql, Entity Framework gibi Orm sistemlerini kullanabiliyoruz. Biz uygulamamızda, Entity Framework'ün Code First yaklaşımını kullanacağız. Bu noktada, veritabanını ve yaklaşımları da kısaca özetleyelim.

Veritabanı : Bir takım verilerin kayıtlı tutulmasını isteriz. Buna örnek olarak, kullanıcı adı ve şifreyi gösterebiliriz. Ancak, bunun gibi bir çok veriyi metin belgesinde tuttuğumuzu düşündüğümüzde, oluşacak karmaşayı da hayal edebiliriz. Veritabanı sayesinde, verilerimizi düzenli, ilişkili (burası önemli, örneğin verilen siparişler ile üyeleri eşleştirerek, kim hangi siparişleri vermiş, rahatlıkla görebiliriz) şekilde saklayabiliriz. Detaylı bilgi için bakınız.

Veritabanı Modelleme Yaklaşımları

  1. Database First : Eğer ki halihazırda, kurulu bir veritabanı varsa bu yaklaşım kullanılır. Sistem otomatik olarak, var olan veritabanında ki kolonları ve satırları, kod tarafında classlara çevirir.
  2. Model First : Görsel bir dizayn aracı ile, modelleme yapılır. Daha sonra sistem, otomatik olarak, veritabanını ve class yapılarını oluşturur. Code First öncesi en popüler yaklaşımdı.
  3. Code First : Son yıllarda en çok kullanılan yaklaşım olup, Microsoft'un sunduğu örneklerde de, en çok bu yaklaşımın kullanıldığı görülmektedir. Bu sistemde ise, veriler tamamen class yapıları olarak, kodlama ile yapılarak, veritabanının otomatik oluşması sağlanır.

Artık projemizi yazmaya başlayalım.

Projemizi Visual Studio 2013 üzerinde, .Net Framework 4.5 altyapısı ile Mvc 5 olarak geliştireceğiz.

  • Öncelikle yeni bir Mvc projesi oluşturalım. Bunun için File>New>Project yolunu izleyelim. (nasıl yapılır için bakınız)
  • Resimde de görebileceğiniz şekilde, .Net Framework 4.5 ü seçip, Asp.Net Web Application'u seçelim, Name kısmına da Mvc Projesi yazıp OK tıklayalım.

Mvc projesinin açılması

  • Açılan ekranda MVC'nin seçili olduğunu doğrulayıp, Authentication : Individual User Accounts olarak seçili olduğunu tespit edelim ve Ok tuşuna tıklayalım.

One Asp.Net

Bu noktada Authentication kısmına da değinmekte fayda var. Change Authentication'a tıklarsak aşağıdaki ekran açılacaktır. Bu sistem Visual Studio 2013'te gelmiştir.

Authentication seçenekleri

Bu ekranda ki seçeneklere bakalım.

  • No Authentication : Bu seçenek seçilirse eğer, sistemde herhangi bir üyelik sistemi aktif olmayacaktır.
  • Individual User Accounts : Eski Asp.Net Authentication'nun yerine gelen, verilerin Sql'de saklandığı, projelerimizin genelinde kullanacağımız üyelik sistemidir. Aynı zamanda bu sistem, Facebook, Open ID, Twitter, Google, Microsoft kullanıcı bilgileriyle giriş imkanı sağlayan yapıya da zemin hazırlamaktadır.
  • Organizational Accounts : Windows Server ve Windows Azure, Active Directory altyapılıüyelik sistemleri için kullanılır.
  • Windows Authentication : Windows kullanıcı bilgileri ile giriş yapmaya izin veren sistemdir. Bu sistem, Intranet gibi şirket içi yapılar için kullanılmaktadır.
  • Projemizi oluşturduktan sonra, öncelikle aşağıdaki listeye göre projemizin içindeki hazır gelen dosyaları silelim.

Silinecekler

  • Content klasörünün içindeki Site.css dosyası
  • Controllers klasörünün içindeki tüm dosyalar
  • Models klasörünün içindeki tüm dosyalar
  • Views klasörünün içindeki Account ve Home klasörü
  • Views>Shared klasörünün içindeki _LoginPartial.cshtml dosyası
  • favicon.ico dosyası
  • Project_Readme.html dosyası

 

  • Temizliğimizi yaptıktan sonra, ana dizinimize Data isimli bir klasör oluşturalım. Bunun için, projemize sağ tıklayıp,  Add>New Folder dememiz yeterli. Bu klasörün altına veritabanını temsil edecek classlarımızı yazacağız.
  • Daha önce, bir blog uygulaması yazacağımızı söylemiştim. Örnek projemizde, kapsamı mümkün olduğunca dar tutmaya çalışacağım. Böylelikle daha rahat kavranması, hedefimiz olacaktır. Bunun için hangi tablolara ihtiyacımız var? Bir düşünelim.​​

 

  • Üyelerin bilgilerinin tutulacağı, Uye tablosu,
  • Makalelerin bulunacağı, Makale tablosu (aynı zamanda, Uye tablosuna bağlantılı olacak),
  • Makale içerisinde, kayıtlı olan etiketlerin bulunacağı, Etiket tablosu (aynı zamanda, Makale tablosuna bağlantılı olacak),
  • Yorumların bulunacağı, Yorum tablosu (aynı zamanda, hem Makale, hem de Uye tablosuna bağlantılı olacak).
  • Yukarıda saydığımız, tablolarımızı hemen Code First ile modellemeye başlayalım.
  • Ana dizindeki, Data klasörümüze sağ tıklayıp, Add>Class diyelim ve adını Uye olarak değiştirip Add tuşuna tıklayalım. Oluşan dosyanın içeriğini, aşağıdaki gibi değiştirelim. (Açıklamalar, yorum satırı olarak, kodların içerisine eklenmiştir.)
using System;
using System.Collections.Generic;

//Bu isim uzayını eklememizin sebebi, [DataType],[StringLength] gibi Attribute'leri tanımlıyor olmamız.
using System.ComponentModel.DataAnnotations;

using System.Linq;
using System.Web;

namespace MvcProjesi.Data
{
    public class Uye
    {
        //Bu alan tablonun id'si olacak. Tablo adının sonuna Id takısı eklendiğinde, framework bu alanı otomatik olarak, 
//tablonun anahtar sütunu yani primary key'si yapacaktır. Bu varsayılanı değiştirmek mümkündür, 
//ancak bu konuya girmeyeceğiz. Detaylı bilgi için, Code First Fluent olarak araştırma yapabilirsiniz.
        public int UyeId { get; set; }

        //Bu alanı zorunlu hale getiriyoruz. Böylelikle boş geçilemeyecek.
        [Required(ErrorMessage = "Lütfen adınızı giriniz.")]
        //Girilen metnin uzunluğunu belirtiyoruz. İlk değişken minimum uzunluk olurken, sonrakiler ise, opsiyonel girdilerdir.
        [StringLength(50, MinimumLength = 3, ErrorMessage = "Adınızı 3-50 karakter arasında girebilirsiniz.")]
        public string Ad { get; set; }

        [Required(ErrorMessage = "Lütfen soyadınızı giriniz.")]
        [StringLength(50, MinimumLength = 3, ErrorMessage = "Soyadınızı 3-50 karakter arasında girebilirsiniz.")]
        public string Soyad { get; set; }

        [Required(ErrorMessage = "Lütfen e-posta adresinizi giriniz.")]
        //Girilen metnin, geçerli bir e-posta adresi formatında girilmesini sağlıyoruz. 
        //DataType tipleri, Microsoft tarafından Framework'e eklenen hazır tiplerdir.
        [DataType(DataType.EmailAddress, ErrorMessage = "Lütfen e-posta adresinizi geçerli bir formatta giriniz.")]
        public string EPosta { get; set; }

        //Required Attribute'si eklemediğimiz için, bu alan zorunlu olmayacak ve boş geçilebiliyor olacak.
        //Girilen metnin, geçerli bir web sitesi adresi formatında girilmesini sağlıyoruz. 
        [DataType(DataType.Url, ErrorMessage = "Lütfen web site adresinizi, geçerli bir formatta giriniz.")]
        public string WebSite { get; set; }

        //Girilen metnin, geçerli bir resim yolu formatında girilmesini sağlıyoruz. 
        [DataType(DataType.ImageUrl, ErrorMessage = "Lütfen resim yolunuzu doğru şekilde giriniz.")]
        public string ResimYol { get; set; }


        [Required(ErrorMessage = "Lütfen üye olma tarihini giriniz.")]
        //Girilen tarihin, geçerli bir tarih ve saat formatında girilmesini sağlıyoruz.
        [DataType(DataType.DateTime, ErrorMessage = "Lütfen üye olma tarihini, doğru bir şekilde giriniz.")]
        public DateTime UyeOlmaTarih { get; set; }

    }
}
  • Yine Data klasörümüze, Makale adında bir class ekleyelim ve içeriğini aşağıdaki gibi düzenleyelim.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace MvcProjesi.Data
{
    public class Makale
    {
        public int MakaleId { get; set; }

        [Required(ErrorMessage = "Lütfen makalenin başlığını giriniz.")]
        [StringLength(50, MinimumLength = 3, ErrorMessage = "Makale başlığı 3-50 karakter arasında olmalıdır.")]
        public string Baslik { get; set; }

        [Required(ErrorMessage = "Lütfen makalenin içeriğini giriniz.")]
        //Girilen metnin, html formatında girilmesini sağlıyoruz.
        [DataType(DataType.Html, ErrorMessage = "Lütfen makale içeriğini html formatında giriniz.")]
        public string Icerik { get; set; }

        [Required(ErrorMessage = "Lütfen makalenin eklenme tarihini giriniz.")]
        [DataType(DataType.DateTime, ErrorMessage = "Lütfen makalenin eklenme  tarihini, doğru bir şekilde giriniz.")]
        public DateTime Tarih { get; set; }

    }
}
  • Şimdi de Data klasörümüze, Etiket adında bir class ekleyelim. ardından içeriğini aşağıdaki gibi düzenleyelim.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace MvcProjesi.Data
{
    public class Etiket
    {
        public int EtiketId { get; set; }

        [Required(ErrorMessage = "Lütfen etiketin içeriğini giriniz.")]
        [StringLength(50, ErrorMessage = "Etiketin içeriği 50 karakterden uzun olamaz.")]
        public string Icerik { get; set; }
    }
}
  • Son olarak da, Data klasörüne Yorum adında bir class ekleyelim. İçeriğini aşağıdaki gibi düzenleyelim.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace MvcProjesi.Data
{
    public class Yorum
    {
        public int YorumId { get; set; }

        [Required(ErrorMessage = "Lütfen yorumunuzu giriniz.")]
        public string Icerik { get; set; }

        [Required(ErrorMessage = "Lütfen yorumun yapılma tarihini giriniz.")]
        [DataType(DataType.DateTime, ErrorMessage = "Lütfen yorum yapılma tarihini, doğru bir şekilde giriniz.")]
        public DateTime Tarih { get; set; }
    }
}
  • Evet, veritabanında tablolarımızı temsil edecek sınıflarımızı oluşturduk. Buraya kadar her şey tamam. Ancak örneğin üyelerin yorumlarını, düzenli bir şekilde kaydedebilmek için, Yorum ile Uye tablosu arasında ki ilişkiyi nasıl kuracağız? Bunun için, aradaki ilişkiyi sağlayacak sql tarafında ki adıyla Foreign Key'lere ihtiyacımız var. Şimdi bu Foreign Key sütunlarımızı tablomuza ekleyelim. 
  • Öncelikle Yorum sınıfımızı aşağıdaki gibi değiştirelim.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace MvcProjesi.Data
{
    public class Yorum
    {
        public int YorumId { get; set; }

        [Required(ErrorMessage = "Lütfen yorumunuzu giriniz.")]
        public string Icerik { get; set; }

        [Required(ErrorMessage = "Lütfen yorumun yapılma tarihini giriniz.")]
        [DataType(DataType.DateTime, ErrorMessage = "Lütfen yorum yapılma tarihini, doğru bir şekilde giriniz.")]
        public DateTime Tarih { get; set; }

        //Her yorum, yalnızca bir makaleye ait olabilir. Bu yüzden, tek bir makaleye bağlıyoruz. 
        //Dikkat edileceği üzere veri türü (burada aynı zamanda sınıf) olarak Makale yazılıyor.
        public virtual Makale Makale { get; set; }

        //Her yorumu, yalnızca bir kişi yazmış olabilir.
        public virtual Uye Uye { get; set; }
    }
}
  • Görüldüğü üzere Yorum sınıfımıza hem Uye, hem de Makale sınıfımızdan link vermiş olduk. Kod içerisinde ki yorum satırlarına lütfen dikkat ediniz. 
  • Şimdi de Uye sınıfımızı aşağıdaki gibi güncelleyelim.
using System;
using System.Collections.Generic;

//Bu isim uzayını eklememizin sebebi, [DataType],[StringLength] gibi Attribute'leri tanımlıyor olmamız.
using System.ComponentModel.DataAnnotations;

using System.Linq;
using System.Web;

namespace MvcProjesi.Data
{
    public class Uye
    {
        //Bu alan tablonun id'si olacak. Tablo adının sonuna Id takısı eklendiğinde, framework bu alanı otomatik olarak, 
        //tablonun anahtar sütunu yani primary key'si yapacaktır. Bu varsayılanı değiştirmek mümkündür, ancak bu konuya 
        //girmeyeceğiz. Detaylı bilgi için, Code First Fluent olarak araştırma yapabilirsiniz.
        public int UyeId { get; set; }

        //Bu alanı zorunlu hale getiriyoruz. Böylelikle boş geçilemeyecek.
        [Required(ErrorMessage = "Lütfen adınızı giriniz.")]
        //Girilen metnin uzunluğunu belirtiyoruz. İlk değişken minimum uzunluk olurken, sonrakiler ise, opsiyonel 
        //girdilerdir.
        [StringLength(50, MinimumLength = 3, ErrorMessage = "Adınızı 3-50 karakter arasında girebilirsiniz.")]
        public string Ad { get; set; }

        [Required(ErrorMessage = "Lütfen soyadınızı giriniz.")]
        [StringLength(50, MinimumLength = 3, ErrorMessage = "Soyadınızı 3-50 karakter arasında girebilirsiniz.")]
        public string Soyad { get; set; }

        [Required(ErrorMessage = "Lütfen e-posta adresinizi giriniz.")]
        //Girilen metnin, geçerli bir e-posta adresi formatında girilmesini sağlıyoruz. 
        //DataType tipleri, Microsoft tarafından Framework'e eklenen hazır tiplerdir.
        [DataType(DataType.EmailAddress, ErrorMessage = "Lütfen e-posta adresinizi geçerli bir formatta giriniz.")]
        public string EPosta { get; set; }

        //Required Attribute'si eklemediğimiz için, bu alan zorunlu olmayacak ve boş geçilebiliyor olacak.
        //Girilen metnin, geçerli bir web sitesi adresi formatında girilmesini sağlıyoruz. 
        [DataType(DataType.Url, ErrorMessage = "Lütfen web site adresinizi, geçerli bir formatta giriniz.")]
        public string WebSite { get; set; }

        //Girilen metnin, geçerli bir resim yolu formatında girilmesini sağlıyoruz. 
        [DataType(DataType.ImageUrl, ErrorMessage = "Lütfen resim yolunuzu doğru şekilde giriniz.")]
        public string ResimYol { get; set; }


        [Required(ErrorMessage = "Lütfen üye olma tarihini giriniz.")]
        //Girilen tarihin, geçerli bir tarih ve saat formatında girilmesini sağlıyoruz.
        [DataType(DataType.DateTime, ErrorMessage = "Lütfen üye olma tarihini, doğru bir şekilde giriniz.")]
        public DateTime UyeOlmaTarih { get; set; }

        //Bir üyenin, birden çok yorumu olabileceği için Yorumları bir liste içerisine alıyoruz. 
        //Property adının sonuna s takısı koymamızın sebebi, veri tipinin çoğul olduğunun daha kolay anlaşılabilmesi 
        //içindir. Entity varsayılan olarak, liste verilerin sonuna s takısı koymaktadır.
        //Biz de bu standarda uyum gösterdik. Eğer veri tipinin adı zaten s ile bitiyorsa o zaman da s yi siliyoruz.
        //Örneğin hayvanlarla ilgili bir tabloda, Kus adlı bir sınıfımız çoğul olarak temsil edilecekse Ku olarak 
        //kullanabiliriz.
        public virtual List<Yorum> Yorums { get; set; }

        //Bir üyenin eklediği, birden çok makale olabilir.
        public virtual List<Makale> Makales { get; set; }
    }
}
  • Yukarıda verilen bilgiler çerçevesinde, diğer sınıflarımızı da güncelleyelim.

Etiket sınıfı

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace MvcProjesi.Data
{
    public class Etiket
    {
        public int EtiketId { get; set; }

        [Required(ErrorMessage = "Lütfen etiketin içeriğini giriniz.")]
        [StringLength(50, ErrorMessage = "Etiketin içeriği 50 karakterden uzun olamaz.")]
        public string Icerik { get; set; }

        //Aynı etiket, birden çok makale de kullanılıyor olabilir.
        public virtual List<Makale> Makales { get; set; }
    }
}

Makale sınıfı

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace MvcProjesi.Data
{
    public class Makale
    {
        public int MakaleId { get; set; }

        [Required(ErrorMessage = "Lütfen makalenin başlığını giriniz.")]
        [StringLength(50, MinimumLength = 3, ErrorMessage = "Makale başlığı 3-50 karakter arasında olmalıdır.")]
        public string Baslik { get; set; }

        [Required(ErrorMessage = "Lütfen makalenin içeriğini giriniz.")]
        //Girilen metnin, html formatında girilmesini sağlıyoruz.
        [DataType(DataType.Html, ErrorMessage = "Lütfen makale içeriğini html formatında giriniz.")]
        public string Icerik { get; set; }

        [Required(ErrorMessage = "Lütfen makalenin eklenme tarihini giriniz.")]
        [DataType(DataType.DateTime, ErrorMessage = "Lütfen makalenin eklenme  tarihini, doğru bir şekilde giriniz.")]
        public DateTime Tarih { get; set; }

        public virtual Uye Uye { get; set; }

        //Bir makalede, birden çok yorum bulunabilir.
        public virtual List<Yorum> Yorums { get; set; }

        //Bir makale de, birden çok etiket bulunabilir.
        public virtual List<Etiket> Etikets { get; set; }
    }
}

Son değişikliklerimizi de yaptıktan sonra, veritabanında bulunacak tabloları, sadece kod ile modellemeyi başardık.

Tablolarımız hazır, bu tablolarımızın oluşturulup, veritabanına kaydedilmesi işlemlerini, bir sonraki dersimizde işleyeceğiz.

Projenin son halini buradan indirebilirsiniz.

Hepinize kolaylıklar diliyorum.