.Net Core Eğitimleri

12- ) Entity Framework – Lazy Loading

Lazy Loading

Bundan önceki derslerde Entity Framework kullanarak nasıl custom şekilde Include işlemleri yapacağımızı gördük. Include işlemini birbiri ile ilişkili tabloların verilerini aynı model içinde göstermek için kullanıyoruz, bir nevi sql üzerinde join işlemi yapmak gibi de düşünebilirsiniz. Farketti iseniz getall, find ve getallwithpaging gibi kayıt çekmek için kullandığımız metodlar var ve biz ilişkili tablolarda bu metodları kullanmak için ilgili controllerda override ederek gerekli bağımlılıkları yani diğer tabloları modele include ettik. Peki her seferinde bu şekilde uğraşacakmıyız? Cevap stratejinize ve kurgunuza göre değişsede her seferinde uzun uzun bu işlemleri yapmak zorunda değilsiniz Lazy loading özelliği bizim için bu işi otomatik olarak yapabilir.

Eğer sisteminizde bulunan ilişkisel tabloların yapısı 3 ya da 4 kat aşağıya inmiyorsa yani örnek vermek gerekirse, Customer içinde organization bilgisi onun içinde ilçe bilgisi onun içinde il bilgisi, ilin içinde ülke bilgisi, … vs gibi alt alta giden bir çok kırılımınız yok ise ve ya gerekli donanımsal kaynaklarınız var ise lazy loading yapısını kullanabilirsiniz. Lazy loading sizin entityleriniz içinde bulunan virtual şeklinde tanımlanmış diğer entity referanslarınızı override ederek içlerini otomatik olarak doldurur. Yani sizin Customer tablonuz içinde virtual olarak tanımlanmış bir organization entity referansı/property si var ise lazy loading onu otomatik olarak ilişkili kayıt ile dolduracaktır.

Artıları

  • Her seferinde include işlemi yapmanıza gerek kalmaz
  • Gerekli tüm bağımlılıkları otomatik olarak aldığı için istemcinin veriye erişmesi kolaylaşır

Eksileri

  • Karmaşık ilişkilere sahip mimarilerde uzun bekleme sürelerine yol açabilir
  • İhtiyacınız olmadığı senaryolarda bile tüm ilişkisel alanlar dolar

Bunlara daha fazla madde eklenebilir ancak en belirgin ve yalın hali ile bu şekilde ifade edilir. Bu özelliği kullanıp kullanmamak tamamı ile sizin senaryolarınıza ve stratejilerinize kalmışdır.

Peki Nasıl Kullanacağız?

Öncelikle “Microsoft.EntityFrameworkCore.Proxies” nuget paketini Data katmanımıza ekleyeceğiz. Bunun için Data projesine solution explorer üzerinden sağ tıklayarak manage nuget packages seçeneğine tıklayalım. Daha sonra arama kımına  “Microsoft.EntityFrameworkCore.Proxies” yazalım ve çıkan paketi seçerek Install tuşuna basalım. Daha önceki derslerde nuget paketlerinin nasıl sisteme eklendiğini detaylıca görmüştük, sorun yaşar iseniz önceki derslere bakabilirsiniz. Paketi projeye ekledikten sonra SolutionExplorer üzerinden Context klasörü altında bulunan ApplicationDbContext.cs dosyamıza çift tıklayalım ve içeriğini aşağıdaki şekilde düzenleyelim.

Artık projemize Lazy loading özelliğini eklemiş olduk. Şimdi dilerseniz override ettiğimiz find,getall metotlarını controllerların içinde yorum satırına alalım. Böylece her iki yöntemde bu projenin içerisinde kalmış olacak, isterseniz lazy loading ile ilgili olan 54. satırı silebilir, controllerlarda bulunan override kodları yorum satırı halinden çıkarabilir ve eskisi gibi çalışmaya devam edebilirsiniz. Ben CustomerController üzerinde bulunan find ve getall metodlarını yorum satırı haline aşağıdaki şekilde getirdim.

Peki şimdi postman üzerinde bir test yapalım ve bakalım organization bilgileri otomatik olarak gelecek mi?

Lazy loading testi
Lazy loading testi

Gördüğünüz gibi dönen json cevabı içerisinde organization sekmesi altında ilişkili olan kayıt otomatik olarak doldu.

Projenin buraya kadar olan kısmı ile ilgili sorun yaşıyorsanız bu link ile github üzerinden projeyi indirebilir ve kendi yazdığınız kodlar ile karşılaştırabilirsiniz. Sorularınız için yorum kısmını kullanabilir ya da mail adresim üzerinde benimle iletişime geçebilirsiniz.
Mail Adresim : mehmetalierol@windowslive.com

<- Önceki Post – Sonraki Post ->

.Net Core Eğitimleri

10- ) Web Api Projesi 1. Kısım

Business Katmanı

Projenin şuana kadar mimarisini oluşturduk, artık web api mizi yani iş katmanımızı kodlayabiliriz. İş katmanı bizim uygulamamızın ne iş yapacağını ve ne senaryolar ile çalışacağını yani işin kendisini kodladığımız yerdir. Bu katman logic ve business katmanı olarak da anılabilir.

Dependency Injection mantığını kullanabilmek adına controllerlarımızın hepsinin ne tür metotlar içereceğini yani metot imzalarını kodlayacağımız interfaceler oluşturacağız. Bunun için web api projesine solution explorer üzerinden sağ tıklayalım ve Interfaces isminde bir klasör oluşturalım. Oluşturduğumuz klasörün üzerine sağ tıklayarak Add –> NewItem diyelim dosya tipimizi Interface işaretleyelim ve Name alanına ILanguageController yazarak kaydedelim.

Controllerların Oluşturulması

Daha sonra ILanguageController.cs dosyasına çift tıklayalım ve içeriğini aşağıdaki şekilde düzenleyelim. Aşağıdaki kodu dikkatli inceleyecek olursanız IApiController Interface inden kalıtım alıyor bu nedenle ortak tüm metot imzaları zaten buraya geleceği için ekstra olarak aynı kodları tekrar yazmamıza gerek yok. Aklınıza neden o zaman bu interface’i oluşturduk sorusu gelebilir, birinci nedeni bu controller içinde farklı ve kendisine özgü metotlar yazabiliriz, ikinci neden ise dependency injection yaparken bu interface üzerinden instance alacağız.

Daha sonra Web api projemiz içerisinde bulunan Controllers sınıfına sağ tıklıyoruz ve Add –> Class diyerek Name kısmına LanguageController yazarak kaydediyoruz. Bu sınıf yukarıda oluşturduğumuz ILanguageController arayüzünden kalıtım alacak. LanguageController.cs dosyamıza çift tıklıyoruz ve içeriğini aşağıdaki şekilde düzenliyoruz.

Yukarıdaki controller içerisinde sadece CheckDublicateLanguage isminde bir metot var geri kalanlar ApiBase üzerinde kodlanmış durumda, api base generic bir sınıf olduğu için içerisine Language entitymizi, LanguageDto sınıfımızı ve Controller’ın kendisini gönderiyoruz. Eğer bu controller diğerlerinden bağımsız bir işlem yapacak ise ya da var olan ortak metotlardan (baseden gelen Add,Update,Delete,Find .. vs gibi) birini override edecek ise sınıfın içerisinde bu kodlamayı yapmamız gerekir. Farklı metotları tabiki bu kısma yazmadan önce interface içerisinde kodlamamız önemli.

LanguageController ile işlemleri bitirdiğimizde ApplicationUserController’ı oluşturacağız. Bu sınıf bizim, Identity yapısını kullanarak kullanıcı işlemleri yapmamızı sağlayacak. Kullanıcı ekleme,silme,güncelleme .. gibi ortak özelliklerin yanında bir sonraki derste göreceğimiz şifre değiştirme, mail adresi üzerinden kullanıcı bulma gibi ekstra metotları da içerecek. Öncelikle interfaceimizi oluşturacağız, bunun için web api projemize içinde bulunan Interfaces klasörüne solution explorer üzerinden sağ tıklıyoruz ve Add –> New Item diyerek, dosya tipi olarak Interface’i seçip Name alanına IUserController yazarak kaydediyoruz.

IUserController.cs dosyasına çift tıklayalım ve aşağıdaki şekilde içeriğini güncelleyelim.

Şimdi sıra UserController’ın kendisini oluşturmaya geldi bu sınıf az önce oluşturduğumuz IUserController arayüzünden kalıtım alacak. Solution explorer üzerinden wep api projemiz altında bulunan Controller klasörüne sağ tıklayalım ve Add –> Class diyerek Name alanına UserController yazıp kaydedelim. Daha sonra UserController.cs dosyasına çift tıklayarak içeriğiniz aşağıdaki şekilde düzenliyoruz.

Son olarak web api projemiz içinde bulunan startup.cs dosyasında çeşitli tanımlamalar yapacağız. Solution explorer üzerinde web api projemiz altında bulunan startup.cs dosyasını bulalım ve çift tıklayarak içini aşağıdaki şekilde güncelleyelim.

Projeyi Ateşliyoruz

Tüm işlemleri tamamladığımızda artık projeyi çalıştırıp test edebiliriz.

Klavyeden F5 tuşuna ya da debug menüsünden start debugging seçeneğine basalım. Uygulamamız çalıştığında tarayıcıda otomatik olarak açılacak ancak karşınıza tarayıcı ekranında 404 not found ibaresi gelecektir. İleriki derslerde projeye swagger kuracağız ve ilk açılışta swagger’ın gelmesini sağlayacağız. Şimdilik ilk testimizi yapmak için tarayıcıda adres satırında uygulamamızın adresinden sonra /Languages/GetAll yazalım ve entera basalım. (benim bilgisayarımda http://localhost:61025/language/getall bu link ile çalışıyor ancak sizde port farklı olabilir.) Eğer tüm işlemler doğru ise karşınıza aşağıdaki gibi bir ekran gelmeli.

Postman ile Testler

Şimdi bir de post örneği yapalım. Bunun için ben postman isimli uygulamayı kullanacağım ve anlatımı onun üzerinden yapacağım. Siz farklı bir uygulama ya da chrome üzerinden bir plug-in seçebilirsiniz, ekranlar aşağı yukarı aynı olacaktır. Postman’ı açtıktan sonra aşağıdaki ekran görüntüsünü takip edelim ve yeni bir dil eklemeyi deneyelim. Business katmanımızda yazdığımız dublicate kontrol sayesinde aynı culture değerine sahip iki farklı kayıt eklememiz engellenmiş olmalı. Deneyip sonucu görelim.

Yukarıdaki adımları tamamladığımız da ilk denememizde sonuç kısmında aşağıdaki şekilde bir görüntü görmeliyiz.

Body kısmında gönderdiğimiz Json içeriği değiştirmeden tekrar Send butonuna basarsak bu sefer aşağıdaki ekranın bizi karşılaması gerekiyor.

Aynı şekilde Yeni bir user eklemek için gereken bilgileri alt kısma yazıyorum. Postman ya da diğer rest tester uygulamaları üzerinden aşağıdaki adımları takip ederek kullanıcı eklemeyi deneyebilirsiniz. Bu işlemlerden sonra mutlaka veritabanınızı kontrol edin ve kayıtların oluşup oluşmadığınız gözlemleyin.

Kullanıcı eklemek için yapılması gerekenler;

1-) Url kısmına –>  http://localhost:61025//User/AddAsync  yazıyoruz ancak dikkat edin sizin uygulamanız farklı bir portta çalışıyor olabilir benim portum 61025.

2-) Body kısmına aşağıdaki JSON’ı yapıştırın ve içeriğini istediğiniz gibi düzenleyin. Language Id kısmına önceden eklediğiniz bir dilin Id sini yazın.

{
“emailConfirmed”: true,
“email”: “test@test.com”,
“userName”: “testuser”,
“password”: “Abc.123”,
“phoneNumber”: “112233445”,
“title”: “Manager”,
“phoneNumberConfirmed” : true,
“languageId” : “fe15e038-a5d4-450a-8c0c-b83d2f502f48”
}

Bir sonraki derste Identity alt yapısını kullanarak kullanıcı işlemlerini(sil,güncelle .. vs) tamamlayacak  ve rol işlemlerini göreceğiz.

Projenin buraya kadar olan kısmı ile ilgili sorun yaşıyorsanız bu link ile github üzerinden projeyi indirebilir ve kendi yazdığınız kodlar ile karşılaştırabilirsiniz. Sorularınız için yorum kısmını kullanabilir ya da mail adresim üzerinde benimle iletişime geçebilirsiniz.
Mail Adresim : mehmetalierol@windowslive.com

<- Önceki Post – Sonraki Post ->

.Net Core Eğitimleri

9- ) WebApi Base Sınıfı

Business kod yazma aşamasından hemen önceki adıma geldik. Bu adımı da tamamladığımızda artık projenin business katmanına yani webapi projemize geçebilir ve istemcilerin birebir iletişime geçecekleri metodlarımızı yazabiliriz. Webapi base sınıfı bizim için bütün ApiControllerın yapacakları ortak işleri tek noktaya toplamak ve tekrarlı kod yazmayı engellemek adına oluşturduğumuz bir sınıftır. Temel olarak ekleme,silme,güncelleme ve seçme işlemleri tüm controllerlarda kullanılacağı için bunları ApiBase sınıfında yöneteceğiz.

Projeden şu zamana kadar yazdığımız neredeyse tüm özellikleri bu sınıf içinde birleştireceğiz. Yavaş yavaş yazdığımız kodlar bir anlam ifade etmeye başlayacak. Sistemin mimarisi bu ders ile tamamlanıyor diyebiliriz.

Common katmanımıza giderek Api klasörünün altında bulunana Base klasörüne sağ tıklayalım ve Add –> Class diyerek Name alanına ApiBase.cs yazarak kaydedelim. Kaydettiğimiz ApiBase.cs dosyasına çift tıklayalım ve içeriğini aşağıdaki şekilde düzenliyelim.

Daha sonra ApiController larımızın interfaceleri için bir Base Interface oluşturalım. Bunun için yine Api klasörü altında bulunan Base klasörüne sağ tıklayarak Add –> Class diyoruz ve Name kısmına IApiController.cs yazarak kaydediyoruz. Daha sonra bu dosyaya çift tıklayacağız ve içeriğini aşağıdaki şekilde düzenleyeceğiz. ApiController larımızın hepsinin bir interface’i olacak ve bu interface i uygulayacaklar.

Bu şekilde işlemleri tamamladığımız da solution explorer üzerinde aşağıdaki ekran görüntüsünü alıyor olmalıyız. Kodların arasına eklediğim yorumları okumanızı tavsiye ediyorum. Bir sonraki dersimizde apicontroller larımızı oluşturarak, iş katmanımızda gerekli işlemleri kodlamaya başlayacağız.

Webapi base sınıfı ders sonrası solution explorer görüntüsü - Mehmet Ali EROL
Webapi base sınıfı ders sonrası solution explorer görüntüsü

Projenin buraya kadar olan kısmı ile ilgili sorun yaşıyorsanız bu link ile github üzerinden projeyi indirebilir ve kendi yazdığınız kodlar ile karşılaştırabilirsiniz. Sorularınız için yorum kısmını kullanabilir ya da mail adresim üzerinde benimle iletişime geçebilirsiniz.
Mail Adresim : mehmetalierol@windowslive.com

<- Önceki Post – Sonraki Post ->

.Net Core Eğitimleri

8 -) Logging ve AutoHistory

Logging ve AutoHistory

Bu yazı ile sistemimize, dosya sistemine loglama(logging on file) ve veritabanında değişikliğe uğrayan kayıtların versiyon versiyon geçmişini tutma yeteneklerini ekleyeceğiz. Loglama ve AutoHistory için ayrı nuget paketlerini projemize dahil edeceğiz. Önceki dersler işlemleri doğru yapıp yapmadığınızı kontrol etmek isterseniz bu link ile projenin son haline github üzerinden ulaşabilirsiniz.

Loglama(Logging)

Sistemimizde olup biten birtakım işlemleri saklamak, gerektiğinde kontroller yapmak ve oluşan hataları detaylıca görmek için loglama işlemleri yaparız. Loglamayı veritabanına, dosya sistemine, nosql bir veritabanına ya da bulut sistemlerine yapabiliriz. Bu örnekler arttırılabilir ancak genel olarak sıklıkla tercih edilen yöntemler bunlardır.  Bir sorunla karşılaşıldığında, şikayet alındığında ya da analiz yapılmak istendiğinde daha önceden yaratılan loglara ulaşmamız gerekebilir. Loglama stratejinizi kurguladığınız sistemin ihtiyaçlarına göre oluşturmalıyız. En önemli nokta loglama yaparken sistemin genel çalışmasının mümkün olduğunca az etkilenmesi ve performans sorunlarının ortaya çıkmamasıdır. Ben en çok tercih edilen loglama çeşitlerinin avantajları ve dezavantajlarından bahsetmeye çalıştım.

1-) Dosya Sistemine Loglama

Loglarımızı dosya sistemi üzerinde tutma işlemidir. Sistemden üretilen tüm loglar belirlenen formatta dosya sistemi üzerinde barındırılır. Dosya üzerine loglama işlemlerinde en önemli noktalardan bir tanesi log dosyasının boyut kontrolüdür. Eğer dosya boyutu kontrolsüz bir şekilde büyüyecek olursa, uygulamamız artık o dosya üzerine log yazmaya çalışırken oldukça fazla zaman harcayacak, belkide hiç loglama yapamayacak hale gelecektir. Bu duruma genelde log dosyasının şişmesi denir. Loglamayı sağlıklı yapamadığımız için sistemin diğer işlevlerinde sorunlar çıkabilir, çok basit işlemler uzun vakitler alabilir ve uygulamamızın geneli bu sorun nedeni ile işlevini yitirebilir. Dosya boyutu mutlaka kontrol edilmeli ve belirlenecek stratejiye göre belli bir boyutun üstüne çıktığında hemen yeni bir log dosyası açarak performans sorunlarının önüne geçilmelidir. Mümkün ise bu logları bir file server üzerine yazmalı ya da en azından farklı bir diske kaydetmemiz daha sağlıklı olacaktır.

Gereksiz loglamadan kaçınmalı ve ihtiyacımız olanı loglayacak şekilde planlama yapmalıyız.  Dosya sistemine aldığımız logların başkası tarafından silinmemesi için gerekli önlemleri almalıyız. Log dosyalarının boyutu sistemin diskini doldurmadan başka bir yere taşımalı ya da ilk yazılan logların otomatik olarak silinmesini sağlayacak şekilde kurallar oluşturmalıyız. Dosya sistemine yazdığımız logları belli bir ayırıcı ile ayırmalı ve programatik olarak okunabilecek seviyede bir veri seti olarak saklamalıyız. Bu logların okunması ve analiz edilmesi, veri tabanına (uygulamanın kendi veritabanı ya da elastiksearch ile nosql çözümleri gibi) yazılan logların analiz edilmesinden daha zor olacaktır ve daha fazla vakit gerektirecektir.

2-) Uygulamanın Veritabanın Loglama

Uygulamanın kendi veritabanına loglama yapma işlemi oldukça kritik işlemler ve kayıtlar için mantıklı olabilir ancak her türlü logun veri tabanına yazılması performans sorunlarına yol açabilir. Mssql veritabanı üzerinden konuşacak olursak, oluşturulan her bir işlemin(transaction) log kaydı veritabanımıza ait log dosyası üzerine yazılmaktadır. Eğer her türlü logu veritabanı yazacak olursak bu bizim için bir transaction olacak ve bizim loglarımız için mssql de log yazma işlemi gerçekleştirecek. Transaction loglar veritabanı için oldukça önemlidir, sistemde yaşanacak sorunlar yanlış yapılan işlemler gibi felaket durumlarında kurtarıcı olabilirler. Yukarıda anlattığım durumda biz bir log işlemi için sisteme iki adet log yazmış olacağız ki bu durumda bizim için maliyet anlamına geliyor. Log şişmesi durumu iyi kontrol edilmeyen ve profesyonel olarak yönetilmeyen veri tabanlarında sıklıkla karşılaşılabilecek bir durumdur. Bu durum ortaya çıktığında veri tabanında uygulamanın da performans sorunları baş gösterecektir.

Veritabanına loglama yapmak geriye dönük aramalarda ve analizlerde oldukça hız kazandıracaktır ancak her türlü loglamanın veritabanına yapılması ciddi bir veri tabanı yönetimi ve senaryolara göre ek maliyetler gerektirecektir.

3-) NoSQL Veritabanlarına Loglama(Elasticsearch)

Bu seçenek son zamanlarda gittikçe popülerleşen bir yaklaşım. Verilerinizi kibana gibi open source elastic search alt yapısına sahip sistemlerde saklayabilir ve MongoDB, Cassandra, CouchDB gibi nosql veritabanları kullanırlar. Başka derslerde bu veritabanlarının çalışma prensiplerinden, artı ve eksi yönlerinden bahsedeceğiz. Şimdilik ilişkisel olmaya şekilde verilerin tutulduğu ve yatay olarak genişleyebilen yapılar olduklarını bilsek yeterli. Bu şekilde loglama yapmak bize analiz ve geriye dönük aramalarda hız kazandıracaktır. Elasticsearch alt yapısı ile saklanan veriler kelime kelime indexlenerek saklanır ve büyük veriler içerisinde arama yapmak oldukça performanslı bir hale gelir.  Ancak bu şekilde bir alt yapı kurmak ve yönetmek ayrı bir maliyettir. Kuracağınız sistemler opensource olduğu için en azından bu sistemlerde oluşabilecek sorunlara müdehale edecek kadar bilgi sahibi olmanız ya da dış destek almanız gerekebilir.

Hangi Yönetimi Kullanmalıyım?

Yukarıda açıklamaya çalıştığım yöntemler dışında, bulut sistemlerine log yazmak, mail ile logları saklamak hatta kullanıcının bilgisayarında log saklamak bile bir yöntemdir ve yerine göre bu yöntemler işimize yarıyabilir. Hangi yönetimi kullanacağımıza, oluşturduğumuz sistemin geneline ve ihtiyaçlarına bakarak(yazılım alanının neredeyse her karşılaştırmasında olduğu gibi) karar vermeliyiz. Az kullanıcılı ve transaction sayısı az olan bir uygulamamız var ise veritabanına loglama yapmak daha akıllıca olabilir ancak işler biraz daha büyüdüğünde hayati loglamaları veritabanına geri kalanları dosya sistemine yapma seçeneğini kullanabiliriz ve artık log dosyalarımız big data seviyelerine gelmeye başladıysa ve geriye dönük olarak tümüne ihtiyacımız varsa elasticsearch yapısından yararlanmak kuvvetli bir seçenek haline gelebilir.

Geliştireceğimiz uygulamanın ne kadar uzun ömürlü olacağı ve kalite algısı bu tarz stratejik kararlara bağlıdır. Geliştirdiğiniz uygulamadan gururla bahsetmek yerine kötü stratejiler yüzünden uygulamanızdan nefret edebilirsiniz. Bir uygulama geliştirirken, desteği, bakımı ve sonradan eklenmesi olası özellikleri düşünerek stratejiler belirlemeli ve planlama aşamasında diğer tüm aşamalardan çok vakit harcamalıyız. Loglama diyerek bu konuyu küçümsemek çok büyük problemlere yol açabilir ve hatta uygulamanızın çalışmasını engelleyebilir.

Uygulamamızın Loglama Altyapısı

Biz uygulamamızda iki farklı seçenek kullanacağız. Stratejimizi veriler ve veriler üzerinde yapılan işlemlere göre iki ana başlıkta belirleyeceğiz. Veriler ile ilgili güncelleme,silme gibi değişiklikleri veri tabanında tutarken, istemcinin api ile haberleşmesi, sistem hata logları ve diğer custom logları dosya sisteminde saklayacağız. Veritabanına loglama için AutoHistory nuget paketini, dosya sistemine loglama için NetEscapades.Extensions.Logging nuget paketini kullanacağız.

.Net Core ile Dosyaya Loglama İşlemleri

Projenin başlangıcında kullandığım dosyaya loglama alt yapısı yerine kullanımı daha kolay olan farklı bir paket keşfettim, bu nedenle Common katmanımız içerisinde bulunan Logging klasörüne ihtiyacımız kalmadı. O klasörü projeden kaldırabiliriz. Daha sonra Solution Explorer üzerinden web api projemize sağ tıklıyoruz ve Manage Nuget Packages diyerek Nuget paket yöneticisini açıyoruz.

Loglama için gerekli nuget paketi yükleme ekranı - Mehmet Ali EROL
Loglama için gerekli nuget paketi yükleme ekranı

Daha sonra aşağıdaki adımları takip ederek ilgili paketi WebApi projemize dahil ediyoruz.

Loglama için gerekli nuget paketi yükleme ekranı 2 - Mehmet Ali EROL
Loglama için gerekli nuget paketi yükleme ekranı 2

Paketi ekledikten sonra projemize bir appsettings.json dosyası ekleyeceğiz. Bu dosyanın içinde loglama ile ilgili ayarları saklayacağız. Bunun için aşağıdaki ekran görüntülerini takip ederek gerekli işlemleri yapalım.

appsettings.json dosyasının projeye eklenmesi - Mehmet Ali EROL
appsettings.json dosyasının projeye eklenmesi
appsettings.json dosyasının projeye eklenmesi 2 - Mehmet Ali EROL
appsettings.json dosyasının projeye eklenmesi 2

WebApi projemize eklediğimiz appsettings.json dosyasına çift tıklayalım ve içeriğini aşağıdaki şekilde düzenleyelim. FileSizeLimit içinde yazan değer 20 megabyte ın byte değeridir ve 20 * 1024 * 1024 şeklinde hesaplanabilir.

WebApi projesi içinde bulunan Startup.cs dosyasına çift tıklayarak aşağıdaki şekilde düzenlemeler yapalım.

Başlangıç projesini WebApi yapmak için Solution Explorer üzerinden WebApi projemize sağ tıklayalım ve Set as Startup Project diyelim. Daha sonra klavyeden F5 tuşuna basabilir ya da Debug menüsünden Start Debugging diyerek projeyi çalıştırabilirsiniz. Proje çalıştığında output tabında çeşitli mesajlar görünecektir. Projeyi durdurarak appsettings.json dosyası içinde Logging segmentinin içinde bulunan “Microsoft”: “Warning” değerini “Microsoft”: “Information” olarak değiştirelim ve tekrar projeyi çalıştıralım. İki şekilde de output tabında görünen değerleri inceleyelim. Information yazdığımızda microsoft ismi ile gelen logların arttığını görebilirsiniz. Daha sonra Solution Explorer kısmına baktığınızda LogFiles klasörünün oluşturulduğunu ve içine bir adet log dosyası yazıldığını görmemiz gerekiyor. Bu dosyanın adı bizim belirttiğimiz gibi applicationLog- ile başlıyor ve bugünün tarihini ile sonlanıyor. Belirttiğimiz sınıra geldiğinde ise aynı isimle yeni bir dosya açılacak ve loglama o dosya üzerinden devam edecek.

Dosyaya loglama alt yapısını oluşturduk ve test ettik. Projenin ilerleyen bölümlerinde custom olarak nasıl log yazacağımızı göreceğiz.

Auto History

Entitylerimiz üzerinde değişiklikler olduğunda bunların loglanması ve geçmişe dönük analiz edilerek gerektiği durumlarda kanıt ya da yol gösterici olarak çekilmesi önemlidir. Bu işlemi kaydın versiyonlarını tutmak da diyebiliriz. İlgili kaydın ilk eklenme zamanından son haline kadar geçirdiği değişimleri saklamak oldukça önemli bir konudur. Özellikle kurumsal projelerde bu kayıt neden değişti ya da bu zamana kadar bu kayıt üzerinde ne değişiklikler yapıldı gibi sorulara cevap vermek hayati önem taşır.

Peki biz bu değişimleri neden dosya sistemine loglamıyoruz? Aslında istersek dosya sisteminde de saklayabiliriz ancak geriye dönük arama yapmak analizlerde kullanmak biraz daha zahmetli bir hal almaya başlayacaktır. Bu loglar ile diğer loglar karışabilir ve aradığımızı bulamaz noktaya gelebiliriz. Bu nedenle bu projede kayıt değişikliklerini AutoHistory ile veri tabanında bir tabloda tutacağız.

İlk olarak Solution Explorer’dan en üstte bulunan Solution adına (Company.Application) sağ tıklayarak nuget paket yöneticisini açıyoruz ve aşağıdaki paketi seçerek Data projesine dahil ediyoruz.

AutoHistory nuget paketinin projeye dahil edilmesi - Mehmet Ali EROL
AutoHistory nuget paketinin projeye dahil edilmesi
AutoHistory nuget paketinin projeye dahil edilmesi 2 - Mehmet Ali EROL
AutoHistory nuget paketinin projeye dahil edilmesi 2

Son olarak Data projemiz altında bulunan Context klasöründeki ApplicationDbContext.cs dosyasına çift tıklıyoruz ve içeriğini aşağıdaki şekilde düzenliyoruz.

Sonuç

Bu ders ile projemize dosyaya loglama ve veritabanına loglama yeteneklerini eklemiş olduk. Buraya kadar yaptığımız işlemleri kontrol etmek isterseniz bu link ile github üzerinden projeye ulaşabilirsiniz. Bu kısım için yaşadığınız bir sorun ya da sormak istediğiniz bir soru varsa yorum kısmında ya da mail adresim üzerinden iletebilirsiniz.
Mail adresim : mehmetalierol@windowslive.com

<- Önceki Post – Sonraki Post ->

.Net Core Eğitimleri

7-) Paging Altyapısı

Paging Nedir ve Neden Kullanılır?

Web apimizi kullanacak istemciler için database üzerinde bulunan kayıtların listesini döneceğimiz metot ya da metotlarımız olacak. Bu metotları kontrol ederek kısıtlamaz isek bağlanan istemci veritabanında bulunan yüksek miktarda veriyi gereksiz yere tek seferde çekmeye çalışabilir. 5000 kayıt barındıran bir müşteri tablomuz olduğunu varsayalım ve bu müşterileri frontend tarafında ekranda listelemeye ihtiyacımız olsun. Kullanıcı bu sayfaya her girdiğinde backend den sürekli olarak 5000 kayıt mı isteyeceğiz? Birde bu uygulamayı yüzlerce kişinin kullandığını düşünecek olursak ortaya ciddi bir alt yapı maliyeti çıkacaktır. Oysaki biz bu 5000 kaydın her seferinde sadece 50 tanesini göstersek ve bir paging alt yapısı kursak, her seferin bir kullanıcı en fazla 50 kayıt görüntüleyebilir ve diğer kayıtları görmek için paging linklerinden faydalanabilir.

Ne elde etmiş olduk?

Bu sayede backend tarafında gereksiz yere kaynak kullanımının önüne geçmiş oluruz. Sadece sunucu tarafında değil aynı zamanda sunucu ve istemci arasında oluşacak trafik üzerinde de ciddi anlamda iyileştirme yapmış oluruz. Common projemizin içinde bulunan paging klasörüne aşağıdaki dosyaları oluşturalım. Paging klasörüne sağ tıklayarak Add –> Class diyoruz ve oluşturacağımız sınıfın adına PagingParams yazarak ekliyoruz. Eklediğimiz PagingParams.cs dosyasına çift tıklayarak aşağıdaki şekilde içeriğini değiştiriyoruz.

Daha sonra paging modeli ile birlikte göndereceğimiz linklerin modelini oluşturuyoruz. Bunun için Paging klasörüne sağ tıklayarak Add –> Class diyeceğiz ve LinkInfo ismi ile kaydedeceğiz. Daha sonra LinkInfo.cs dosyasına sağ tıklayarak aşağıdaki şekilde içeriğini değiştireceğiz.

Sayfalanmış bir model geriye dönerken bu modele bir header bölümü ekleyeceğiz. Bu header kısmında kaç adet muhtemel sayfa olduğu, şuan kaçıncı sayfanın frontend e gönderildiği, gönderilen sayfada kaç satır bilgi olduğu ve toplam tüm sayfaların satır sayılarının toplamı gibi bilgiler vereceğiz. Bunun için Paging klasörüne PagingHeader isminde bir sınıf oluşturacağız. Oluşturduğumuz PagingHeader.cs dosyasına çift tıklayarak içeriğini aşağıdaki şekilde düzenleyelim.

Sayfalama yapılmış bir liste oluşturmak için biraz önce oluşturduğumuz PagingHeader sınıfınıda içerecek bir sınıf oluşturacağız. Bu sınıf bizim için sayfalanmış bir sonuç ve bu sonuca dair header bilgilerini tutacak. Paging klasörüne sağ tıklıyoruz Add –> Class diyerek Name alanına PagedList yazıyoruz ve kaydediyoruz. Daha sonra eklediğimiz PagedList.cs dosyasına çift tıklayarak içeriğini aşağıdaki şekilde düzenliyoruz. 

Yukarıda kodladığımız paging yapısını birleştirecek ve geri dönüş için kullanılacak bir sınıf oluşturacağız. Bu sınıfa OutputModel ismini vereceğiz. Tüm sayfalama işlemleri tamamlandığında bu sınıf içinde son halini alacak ve istemciye gönderilecek. Bunun için Paging klasörüne sağ tıklıyoruz Add –> Class diyoruz ve Name alanına OutputModel yazarak kaydediyoruz. Daha sonra OutputModel.cs dosyasına çift tıklayarak içeriğini alağıdaki şekilde değiştiriyoruz.

Paging klasörünün altına Interfaces isminde bir klasör açıyoruz, bu klasör bizim için interfaceleri barındıracak. Sonra bu Interfaces klasörü içerisine IPagingLinks isminde bir interface oluşturuyoruz. Oluşturduğumuz IPagingLinks.cs dosyasına çift tıklayalım ve aşağıdaki şekilde içeriğini düzenleyelim.

Son olarak linkleri oluşturacak ve IPagingLinks arayüzünü implemente edecek sınıfımızı oluşturuyoruz. Öncesinde IPagingLinks arayüzünü oluşturma sebebimiz dependency injection kullanabilmek.

Interface’ler ve Dependency Injection

Uygulamamızın mümkün olduğunca doğrudan bağımlılıklara sahip olmasını engellememiz gerekiyor. Dependency injection ile bu bağımlılıkları arayüzler vasıtası ile enjekte ediyoruz. Örnek verecek olursan bu sınıfın yaptığı işi daha farklı şekilde yapan başka bir sınıfımız olabilir ve biz bu backend projeyi A müşterisinde mevcutta yazdığımız şekilde B müşterisinde başka bir sınıfla yapmak mecburiyetinde kalabiliriz. Bu durumda eğer arayüzler ile çalışarak dependency injection kullanıyor isek yapmamız gereken tek şey o arayüzü implemente eden iki farklı sınıf yazmak ve ileride göreceğimiz startup.cs dosyası içerisinde deploy aşamasında hangi sınıfın bu arayüz ile eşleştirileceğini belirtmek olacak. Paging klasörüne sağ tıklayalım Add –> Class diyerek Name alanına PagingLinks yazarak kaydedelim. Daha sonra bu dosyaya çift tıklayarak içeriğini aşağıdaki şekilde güncelliyoruz. 

Sonuç

Bu son işlemi de yaptığımızda artık paging alt yapımız hazır hale gelmiş oluyor. Eğer işlem adımlarını doğru uyguladıysak Solution Explorer üzerinde aşağıdaki ekran görüntüsündeki gibi bir yapı görüyor olmalıyız.

Paging nedir, paging yapısı
Paging işlemlerinin doğru yapılması sonucunda görülmesi gereken sonuç.

Common projemiz için tek eksik kalan nokta AutoHistory ve logging alt yapısı. Sonraki derste bu özellikleri projemize dahil edeceğiz.  Buraya kadar olan kısmı kontrol etmek için projenin son haline github sayfamdan bu link ile ulaşabilirsiniz. Benimle iletişime geçmek için yorum kısmını kullanabilir ya da mail atabilirsiniz. 
Mail Adresim : mehmetalierol@windowslive.com

<- Önceki Post – Sonraki Post ->

.Net Core Eğitimleri

6-) Generic Repository ve UnitofWork

Başlarken

Önceki derslerde projemizde code first ile veritabanı tasarımı yapmıştık. Peki bu tablolar üzerinde CRUD(Create, Read, Update, Delete) işlemlerini nasıl yapacağız? Eğer klasik yöntemleri kullanacak olsaydık yüksek ihtimal ile her bir entity için ayrı ayrı yönetim sınıfları oluşturacak ve aynı kodları tekrar tekrar yazacaktık. Bu dersimizde Generic Repository ve UnitofWork desenlerini projemize dahil edeceğiz.

Generic Repository ve Unitofwork

Yazılım geliştirmede en önemli konulardan bir tanesi ortak noktaları görmek ve tekrarlı kod yazmaya yönelten tasarımlardan uzak durmaktır. Tüm entity lerimizde yapacağımız işlemler temelde aynı. Hepsinde ekleme, silme, seçme, güncelleme işlemleri yapacağız. Tabiki her entity’nin business ile ilgili ekstra kodları olacaktır ancak o kodlar o entitye özel olacağı için tekrarlı kod yazmak anlamına gelmeyecek sadece bir kez yazılacaklardır.  Repository pattern ile bu ortak işlemleri generic bir sınıf oluşturarak tek bir noktadan yürütebiliriz. Üzerinde CRUD işlemler yapmak istediğimiz entity sınıfımızı generic type olarak Repositorye gönderdiğimizde geri sadece yapmak istediğimiz işin komutunu vermek kalacak. Biz bu uygulamamızda Generic Repository ve UnitofWork alt yapısını kullanacağız. Repository bizim için yapılacak işleri bir kuyruğa ekleyecek ve zamanı geldiğinde unitofwork bu kuyrukta bulunan işlerin veritabanında gerçekleşmesini sağlayacak. Unitofwork genellikle sıralı işlere sahip uygulamaların alt yapısında kullanılmaktadır.

Günlük hayattan bir örnek vermeye çalışırsak bir oto kuaförümüz olduğunu varsayalım, işletmemizin cilalama, iç yıkama ve dış yıkama hizmetleri olsun. Her bir hizmeti yapmak için ayrı bölmelerimiz olduğunu varsayalım(İç yıkama alanı, dış yıkama alanı, cilalama alanı). Ödemeyi almadan da hizmet vermiyoruz. Müşteriler araçları getirdiğinde onları bizim Repository Ahmet karşılayacak  ve araca ne işlem yapılması gerektiğini öğrenerek ilgili hizmetin bölmesinde aracı sıraya sokacak(A aracına iç yıkama, B aracına cilalama .. vs). Burada dikkat etmemiz gereken husus araçlara henüz işlem yapılmadı ama işlem yapılmak üzere etiketlendi ve kuyruğa eklendi. Bu arada unitofwork Hasan ödemesi yapılan yani SaveChanges işlemini yapmış müşterilerin araçlarını gerekli işlemleri yapmak üzere ilgili bölümlere yönlendirecek ve artık fiziki olarak hizmet tamamlanmış olacak. Böylece bu işlemleri izole ettik ve birbirinden ayırdık. Herkes kendi işini yapıyor ve yönetilmesi daha kolay bir yapı ortaya çıkıyor. Zorlarsak kabaca bu şekilde bir yapı var diyebiliriz. :)

IGenericRepository Arayüzü

Şimdi Repository için önce bir Interface oluşturacağız ve repository içinde yapılmasını istediğimiz işlemlere ait metotların imzalarını tanımlayacağız. Interfacelerde metotların body’leri olmaz sadece ve sadece imzaları dediğimiz kısım yani ne parametre aldıkları ve ne cevap döndükleri bilgisi bulunur. Interface oluşturmak için aşağıdaki ekran görüntüsünü takip edebilirsiniz.

Generic Repository Interface'inin eklenmesi - Mehmet Ali EROL
Generic Repository Interface’inin eklenmesi

Common projemiz içerisinde bulunan Repository klasörüne sağ tıklayarak “Add –> Class” diyoruz.

Generic Repository Interface'inin eklenmesi 2 - Mehmet Ali EROL
Generic Repository Interface’inin eklenmesi

Açılan ekranda nesne tipi olarak interface seçiyoruz ve Name alanına IGenericRepository yazarak kaydediyoruz.

Eklediğimiz IGenericRepositoru interface’ine çift tıklayarak dosyayı açıyoruz ve içeriğini aşağıdaki şekilde düzenliyoruz.

GenericRepository Sınıfı

Artık projemizde kullanacağımız Repository nin hangi metotları içermesi gerektiğini biliyoruz. Sıra GenericRepository sınıfımızı oluşturmaya geldi.

Generic Repository sınıfının eklenmesi - Mehmet Ali EROL
Generic Repository sınıfının eklenmesi

Repository klasörüne sağ tıklayarak tekrar “Add –> Class” diyoruz.

Generic Repository sınıfının eklenmesi 2 - Mehmet Ali EROL
Generic Repository sınıfının eklenmesi 2

Daha sonra açılan ekrandan nesne tipini class olarak seçiyoruz ve Name alanına GenericRepository yazarak kaydediyoruz.

Oluşturduğumuz GenericRepository.cs dosyasına çift tıklıyoruz ve içeriğini aşağıdaki şekilde düzenliyoruz.

IUnitofWork Arayüzü

Repositoryden sonra sırada UnitofWork sınıfı var, bu sınıfı oluşturmak için yine bir interface ekleyerek metot imzalarımızı yazacak ve bir unitofwork sınıfında neler bulunması gerektiğini belirteceğiz. Bu kez Common projemiz altında bulunan UnitofWork klasörüne sağ tıklıyoruz ve “Add –> Class” dedikten sonra nesne tipi kısmından interface’i seçip Name alanına IUnitofWork yazarak kaydediyoruz.

Oluşturduğumuz IUnitofWork.cs dosyasına çift tıklayarak içeriğini aşağıdaki gibi düzenliyoruz.

UnitofWork Sınıfı

Son olarak UnitofWork sınıfımızı oluşturacağız, bunun için UnitofWork klasörüne sağ tıklayarak “Add –> Class” diyoruz ve Name alanına UnitofWork yazarak kaydediyoruz.

Unitofwork.cs dosyasına çift tıklayarak içeriğini aşağıdaki gibi düzenliyoruz.

Generic Repository ve Unitofwork dersi sonucunda SolutionExplorer görüntüsü - Mehmet Ali EROL
Generic Repository ve Unitofwork dersi sonucunda SolutionExplorer görüntüsü

Buraya kadar yaptığımız işlemleri doğru yaptı iseniz Solution Explorer üzerinde aşağıdaki gibi bir görüntü görüyor olmanız gerekiyor.

Kontrol etmek isterseniz projenin son haline github sayfam üzerinden bu link ile ulaşabilirsiniz. Sormak istediğini herhangi bir soru var ise yorumlar kısmından ya da mail adresim üzerinden bana ulaşabilirsiniz.
Mail Adresim : mehmetalierol@windowslive.com

<- Önceki Post – Sonraki Post ->

.Net Core Eğitimleri

4-) Data Katmanı ve Migration

Data Katmanı

“Common” katmanını genel hatları ile oluşturduktan sonra sırada “Data” katmanımız var. Data katmanımızı code first migration yaparak veritabanımız üzerinde tabloları otomatik oluşturacak şekilde kurgulayacağız. “Solution Explorer” üzerinden Data projesinin üzerine sağ tıklayarak “Context” ve “Entites” isminde iki adet klasör ekliyoruz. İlk etapta bu klasörler boş olacak.”ConnectionString” tanımlamak için projeye bir ayar dosyası ekleyeceğiz ve bu dosyadan connection stringi okuyacağız. .Net Core öncesinde bu ayar dosyası xml formatında olur ve ismi web.config olurdu. Artık core ile birlikte json formatında bir ayar dosyası kullanılmakta.Tabi bu bir zorunluluk değil.

Biz projemize “appsettings.json” isminde bir dosya ekliyoruz. Aşağıda bulunan ekran görüntüsünde olduğu gibi önce arama kısmına “json” yazarak bir filtreleme yaptık ve sonuçlar içerisinden “JSON File” seçeneğini işaretleyerek, isim kısmına “appsettings.json”  yazdık.

appsettings.json dosyasının eklenmesi - Mehmet Ali EROL
appsettings.json dosyasının eklenmesi – Code First Migration

Connection String

Bu işlemi yaptıktan sonra “Solution Explorer” üzerinde gördüğümüz “appsettings.json” dosyasına çift tıklayarak açıyoruz ve içini aşağıdaki gibi düzenliyoruz.

Entity ‘lerin Oluşturulaması

Şimdi tek tek projemize entitylerimizi ekleyeceğiz, ekleyeceğimiz her bir class, “Common” katmanımızda kodladığımız “EntityBase” isimli sınıftan kalıtım(inheritance) alacak. “Entities” klasörüne sağ tıklayarak “Add –> Class” diyoruz ve açılan kısımda “Name” alanına
“Customer.cs” yazarak ekliyoruz. “Customer” bizim müşterilerimizin bilgilerini tutacak nesne olacak. “Customer” nesnesini oluşturduğumuz gibi “Organization”, “Language”, “AppResource” nesnelerini de oluşturalım. Bu nesneleri tamamen örnek olması açısından ekliyoruz ve projenin ilerleyen bölümlerinde bu nesneler üzerinde çeşitli işlemler yapacağız. “Organization” nesnesi bizim uygulamamız için firmaların bilgilerini tutacak, “Language” nesnesi çoklu dil alt yapısı kurmak için desteklenen dilleri tutacak ve “AppResource” nesnesi ise çevirilerin yer aldığı nesne olacak.

Bu sınıfların Common katmanında bulunan EntityBase nesnesinden kalıtım alabilmeleri için Common projesini referans olarak Data projesine eklemeliyiz.

Common projesinin referans olarak eklenmesi - Mehmet Ali EROL
Common projesinin referans olarak eklenmesi – Code First Migration
Common projesinin referans olarak eklenmesi 2 - Mehmet Ali EROL
Common projesinin referans olarak eklenmesi 2 – Code First Migration

Karşımıza çıkan pencereden Company.Application.Common seçeneğini seçili hale getiriyoruz.

Yukarıdaki şekilde referans ekleme işlemini yaparak, saydığımız nesneleri oluşturduktan sonra her birinin içeriğini aşağıdaki şekilde güncelleyelim.

Identity Altyapısı

Microsoft.AspNetCore.App paketinin projeye dahil edilmesi - Mehmet Ali EROL
Microsoft.AspNetCore.App paketinin projeye dahil edilmesi – Code First Migration

Projemizde Identity alt yapısını kullanarak authentication ve authorization işlemlerini yapacağımız için “IdentityUser” nesnesinden kalıtım alan ve kullanıcılarımızın bilgileri saklayacağımız class’ımızı oluşturuyoruz.
Entities klasörüne sağ tıklayarak “Add –> Class” yolunu izliyoruz ve yeni dosya ekleme kutusunda “Name” alanına “ApplicationUser.cs” yazıyoruz. Bu nesne bizim uygulamamızı kullanacak kişilerin bilgilerini barındıracak ve “IdentityUser” base classından kalıtım alacak.
“IdentityUser” nesnesini kalıtım alabilmek için aşağıdaki ekran görüntüsünde de görüldüğü gibi “Data” projesine sağ tıklayarak “Manage Nuget Packages” seçeneğine tıklıyoruz.

Ardından karşımıza nuget paket yöneticisi ekranı gelecek. Yine aşağıdaki ekran görüntüsünü takip ederek arama kısmına “Microsoft.AspNetCore.App” yazarak arama yapıyoruz ve 2 nolu ok ile işaret edilen seçeneğe tıklıyoruz.  En son 3 nolu ok ile işaret edilen Install butonuna tıklıyoruz. Genelde bu işlemleri yaptığınızda kısa bir bekleme sonrasında size bir onay kutusu gösterir, devam edebilmek için gelen ekranda “Kabul Ediyorum (I Accept)” seçeneğini tıklayalım. Aynı işlemi bu projeye referans verdiğiniz Common projesi için de yapacağız. Lütfen aynı adımları uygulayarak Common projesinede “Microsoft.AspNetCore.App” bağımlılığını yükleyelim.

Microsoft.AspNetCore.App paketinin projeye dahil edilmesi 2 - Mehmet Ali EROL
Microsoft.AspNetCore.App paketinin projeye dahil edilmesi 2 – Code First Migration

IdentityUser

Bu işlemi yaptıktan sonra artık “ApplicationUser.cs” dosyasına çift tıklayarak içeriğini aşağıdaki gibi düzenliyoruz. Koda dikkat edecek olursanız sınıfımız “IdentityUser” base sınıfından kalıtım aldı. “IdentityUser” üzerine tıklayarak klavyeden “F12” tuşuna basabilir ve bu sınıfın içinde ne gibi property ler olduğuna bakabilirsiniz.

IdentityRole

ApplicationUser’ı ekledikten ve gerekli düzenlemeleri yaptıktan sonra Entities klasörüne sağ tıklayarak “Add –> Class” yolunu izliyoruz ve  Rollerimiz için ApplicationRole isimli bir sınıf oluşturuyoruz. Nasıl ki ApplicationUser sınıfımız IdentityUser sınıfından kalıtım aldı ise ApplicationRole sınıfımızda IdentityRole sınıfını kalıtım alacak. Dosyayı ekledikten sonra ApplicationRole.cs dosyasına çift tıklıyoruz ve aşağıdaki şekilde içerisini güncelliyoruz.

Şimdi kullanıcılar ve rollerin eşleştirildiği ApplicationUserRole isimli bir sınıf oluşturacağız ve bu sınıf IdentityUserRole sınıfından kalıtım alacak. Identity alt yapısında kullanıcı yönetimi için UserManager sınıfı kullanılıyorve bu sınıf ile biz sadece kullanıcıya ait rollerin adını alabiliyoruz. Bu nedenle entity framework alt yapısı ile Identityi birleştireceğiz. Entities klasörü içerisine oluşturduğumuz ApplicationUserRole.cs dosyasına çift tıklayarak içeriğini aşağıdaki gibi düzenliyoruz.

Diğer Identity Sınıfları

Entities klasörüne sağ tıklayarak ApplicationUserRole isminde yeni bir sınıf oluşturuyoruz. Bu sınıf bizim User ve Role lerimizin birleşim tablosu yani many to many relation tablomuz olacak. Bu sınıfı ve bundan sonra oluşturacağımız ApplicationUserToken ve ApplicationUserLogin sınıflarını oluşturmak zorunlu değil ancak bu sınıflarda bir id property si bulunmuyor bu nedenle ilerleyen derslerde göreceğimiz AutoHistory ve ApiBase sınıflarımızda sorunlar yaşamamak için ekliyoruz. Identity alt yapısında başka sınıflarda mevcut ancak o sınıflarda Id propertyleri olduğu için bir sorun yok. Siz mevcut Identity sınıflarını genişletecek başka özellikler ekleyecekseniz dbcontext constructor metodunda generic type olarak verdiğimiz tüm Identity sınıflarından kalıtım alan kendi sınıflarınızı oluşturabilirsiniz.

Sırası ile ApplicationUserRole (IdentityUserRole’den kalıtım alacak), ApplicationUserToken(IdentityUserToken’dan kalıtım alacak) ve ApplicationUserLogin(IdentityUserLogin’den kalıtım alacak) sınıflarımızı oluşturacağız bunlar bizim kendi sınıflarımız isimlerine istediğimizi verebiliriz.

ApplicationUserRole

ApplicationUserToken

ApplicationUserLogin

DbContext

Artık son aşamaya geldik diyebiliriz. Bu aşamada “DbContext” imizi oluşturacağız. Normal şartlarda oluşturacağımız context sınıfı “DbContext” sınıfından kalıtım alacaktı ancak biz projemizde “IdentityUser” alt yapısını kullandığımız için context sınıfımız generic olan “IdentityDbContext<>” sınıfından kalıtım alacak. Bu generic sınıf tip olarak içerisine IdentityUser’ı kalıtım almış bir sınıfı ve IdentityRole sınıfını kalıtım almış diğer bir sınıfı beklemektedir ki bizde bir adım öncesinde bu sınıfları oluşturmuştuk. Yazının başında oluşturduğumuz “Context” isimli klasöre sağ tıklayalım ve “New –> Class” diyerek yeni bir sınıf oluşturalım ve sınıfımızın adına “ApplicationDbContext.cs” diyelim. Daha sonra bu dosyaya çift tıklayarak içeriğini aşağıdaki gibi düzenleyelim.

Migration Altyapısı

Migration yapabilmek için IDesignTimeDbContextFactory isimli generic interface’i implemente eden bir sınıf oluşturacağız ve bu interface’e oluşturduğumuz ApplicationDbContext sınıfını tip olarak göndereceğiz.
Context klasörümüze sağ tıklayarak “Add –> Class” yolunu izliyoruz ve Name alanına DesignTimeDbContextFactory.cs yazarak kaydediyoruz. Oluşturduğumuz dosyaya çift tıklayarak içini aşağıdaki şekilde düzenliyoruz.

Code First Migration

Migration ekleme işlemi - Mehmet Ali EROL
Migration ekleme işlemi – Code First Migration

Mssql management studio görüntüsü - Mehmet Ali EROL
Mssql management studio görüntüsü – Code First Migration
Update database komutu ile veritabanı oluşturma işlemi - Mehmet Ali EROL
Update database komutu ile veritabanı oluşturma işlemi – Code First Migration

Tüm işlemleri yaptığımızda artık “code first” yaklaşımı ile veritabanımızı kodlamış oluyoruz. Tabiki daha sonradan eklenecek tablolar ve sütunlar olacaktır. Biz projemizin veritabanının bu hali ile “MsSQL server” üzerinde oluşturulması için migration işlemi yapacağız. “Migration” işlemi oluşturduğumuz “ApplicationDbContext” içerisindeki ayarları ve “DbSet” ile tanımladığımız tabloları bizim belirlediğimiz kurallar çerçevesinde “MsSQL” üzerinde oluşturma işlemidir diyebiliriz. Bu işlemi “Package Manager Console”(biz artık PMC diyeceğiz) üzerinden yapacağız. Eğer PMC yi ekranda göremiyorsanız, “Tools” menüsünden “Nuget Packege Manager — > Package Manager Console” yolunu izleyerek açabilirsiniz.

Add-Migration Komutu

PMC ye tıklayarak  “Add-Migration migrationAdı”  şeklinde bir komut yazacağız. Bu migration bizim için ilk olacağından dolayı ben adına ilk anlamına gelen “initial” ismini vereceğim.  Bu işlemi yaparken PMC üzerinde “Default project” alanında “Data” projemizin seçili olduğundan emin oluyoruz ve aynı zamanda Data projemize sağ tıklayarak “Set as Startup Project” demeyide unutmuyoruz.

İşlemleri doğru bir şekilde yaptıysak “Solution Explorer” üzerinde aşağıdaki gibi bir ekran görüntüsü görmemiz gerekiyor.

Peki buraya kadar yaptıklarımız code first ile oluşturduğumuz database tasarımının MsSQL üzerinde oluşmasını sağladı mı? Sorunun cevabını verebilmek için hemen MsSQL Management Studio yu açıyoruz. Databases kısmında connection string içinde belirttiğimiz üzere ApplicationDB isminde bir veritabanı olması gerekiyor. Ama aşağıdaki ekran görüntüsünden de anlaşılacağı üzere veritabanı listede görünmüyor.

Update-Database Komutu

Veritabanının oluşmaması gayet normal çünkü biz şuana kadar sadece migration oluşturduk yani veritabanı oluşturmak için gereken son hamleyi henüz yapmadık. Migration ile bir plan hazırladık, yani örnek üzerinden gidecek olursa arabanın çalışması için gereken herşeyi oluşturduk sadece marşa basmak kaldı. O zaman yine PMC üzerinden update-database komutunu girerek marşa basalım.

Bu işlem sonrasın tekrar MsSQL Management Studio üzerinden kontrollerimizi yapıyoruz ve veritabanımızın oluşup oluşmadığını kontrol ediyoruz.

Sizde yukarıdaki ekran görüntüsünü görüyorsanız işlemleri doğru bir şekilde yapmışız demektir. Farkettiyseniz identity yapısını projemize dahil ettiğimiz için Identity tabloları veritabanında otomatik olarak oluşturuldu. Herhangi bir adımda hata ile karşılaştıysanız ya da kendi kodunuz ile benim yazdığım kodu karşılaştırmak istiyorsanız projenin son haline github sayfamdan ulaşmak için bu link ‘e tıklayabilirsiniz.

<- Önceki Post – Sonraki Post ->