ASP.NET - MVC Framework - II

Bir önceki makalemizde MVC Framework ‘ün ne iÅŸe yaradığını, nasıl bir mimari düşünce içersinde çalıştığını ve bu mimarinin bize katkılarının neler olduÄŸuna deÄŸinmeye çalıştık. Sonrasında ise ilk MVC uygulamamızı açarak bize hazır olarak oluÅŸturulan klasörlerin sınıfların ve web servis kontrollerine göz atmaya çalıştık. Daha sonrasında ise View ve Controller içeriklerini kontrol ederek iÅŸlemlerimizi tamamlamış olduk.

View ve Controller kavramlarını inceledik fakat bir diÄŸer katman olan Modele yalnızca isim olarak deÄŸindik ve ne iÅŸe yaradığından bahsetmiÅŸtik. Bu makalemizde ise MVC Framework ‘te veri tabanı iÅŸlemlerimizi yapmamıza yarayacak olan Model katmanını incelemeye çalışacağız.

Model katmanını incelerken LinQ to SQL ile sorgularımızı daha nesnesel bir şekilde kullanırken veri tabanı olarak da SQL SERVER 2005 ile birlikte gelen örnek veri tabanlarından Adventure Work 'u kullanacağız.



Yazımızın ayrıntılarına girmeden önce isterseniz tekrardan Modelin ne olduğunu hatırlayalım.

Model: Model genellikle veri tabanı iÅŸlemlerimizi yani iÅŸlerimizi( business ) yaptığımız yapıdır. Veri tabanımız üzerinde yapılabilecek sorgularımızı burada belirler ve Controller ’ı atamamızı saÄŸlarız. Bu sayede veri tabanımıza dışarıdan daha kolay eriÅŸebilir ve çeÅŸitli metotlarla daha kolay idare/müdahale edilebilir hale getirir.

Şimdi model katmanını incelemeye başlayabiliriz. Model veri tabanı işlemlerinin yapıldığı bir katman olduğundan ötürü bizde bunu örnek üzerinden anlatmaya çalışacağız.

Uygulamamıza başlarken File-->New-->Project adımlarını izleyerek ASP.NET MVC Web Application seçeneğini seçiyoruz. Projemizin ismini de AdventureWorkMerhaba olarak belirledikten sonra projeyi tamam butonuna basarak uygulamamızı oluşturuyoruz.



Veri tabanımızı uygulamamıza ekleyebilmek için Server Explorer bölümünden Data Connections ‘ın üzerinde saÄŸa tıklayarak Add Connection seçeneÄŸini tıklarız.



Karşımıza Server adını ve veri tabanı ismini girmemizi isteyen bir ekran gelecektir. Bu bölümde de server ismini (eÄŸer SQLExpress kullanıyorsanız server ismi = sqlexpress ‘tir) girdikten sonra database isminin olduÄŸu bölümün içeriÄŸi otomatik olarak bizim üzerinde çalışmakta olduÄŸumuz veri tabanları ile doldurulur. Bizde oradan AdventureWork ‘ü seçerek tamam dediÄŸimizde artık uygulamamızın bir veri tabanı oluyor.



Uygulamamızda kullanacak olduğumuz veri tabanına ait sorgularımızı model katmanının içerisinde oluşturacağımızdan ve bu sorguları da LinQ to SQL yardımı ile yapacağımızdan bahsetmiştik. Bu sebepten ötürü Model klasörümüzün içerisine gerekli olan sınıfı eklememiz için model klasörünün üzerine sağa tıklayarak Add-->NewItem basamaklarını uygulaya biliriz.



Yeni öğe ekleme seçeneÄŸinin içeriÄŸi açıldığı zaman karşımıza her zamankinden farklı öğeler karşılamaktadır. Karşılaşılan öğeler MVC ile ilgili olanlardır. Bunların listede yer almasının baÅŸlıca sebebi MVC Framework ‘ü kurmamızdır. EÄŸer bu Framework ‘ü kurmadan MVC uygulaması yapmaya çalışsaydık daha önceki zamanlarda olduÄŸu gibi bu öğelerin hazırlanması içinde uzunca bir zaman ayırmamız gerekecekti.



Bu öğeleri bir kenara bırakırsak bizim iÅŸimize yarayacak olan sınıfı eklemek için karşımızda listeden LinQ to SQL Classes ‘ı bularak ismini AdventureWork olarak belirledikten sonra tamamı seçerek uygulamamıza ekliyoruz.



Eklediğimiz zaman dikkatimizi çeken birkaç nokta oluyor. Bunlardan birinci referanslar bölümünde yeni eklenen referansların olması. Bu referanslar LinQ to SQL ile ilgili sınıfları ve özellikleri kullanmamız için gereklidir.



İkincisi ve en önemlisi olanda *.dbml uzantılı bir dosya oluşturuyor. DBML database Markup Language anlamına gelen ve yardımcı veri olarak kullanılmakta olan bir sınıftır.

AdventureWork.dbml ‘imizi oluÅŸturduÄŸumuzda bizden uygulamamızdaki veri tabanına iliÅŸkin tabloları eklememizi beklemeye baÅŸlayacaktır. Åžimdi de bu iÅŸlemleri nasıl yapacağımıza deÄŸinmeye çalışalım.

Daha önceden eklemiÅŸ olduÄŸumuz veri tabanının tablolarından ihtiyacımız olanları Object Relationel Designer (ORD) yazan yere sürükleyip bırakıyoruz. Biz bu uygulama için tablolardan Product, ProductOrderDetail ve ProductCategory ‘i ORD ‘ye sürükleyerek tabloların ve bu tablolara ait özelliklerin ekran gözükmesini saÄŸlamış oluruz. Ayrıca bu tablolar arasında herhangi bir iliÅŸki var ise onlarda otomatik olarak ekranda oluÅŸturulacaktır.


İlişkileri oluşmuş olan tablolarımızı kaydedip kapattıktan sonra dmbl dosyamızın arka planında oluşan kodlarına göz atalım. Bakalım veri tabanı tablolarımız ve bu tablolarımıza ilişkin özellikler nasıl oluşmuş.

Oluşmuş olan kodları aşağıdaki tablonun içersinde bulabilirsiniz. Fakat verecek olduğumuz kod bloğu oluşturulmuş olan kodun tümü değildir. Bunun sebebi ise yaklaşık 1250 satır kodun oluşturulmasıdır.

Kodları vermeden önce daha önceden asp.net, Java veya başka bir dille oluşturmuş olduğumuz model sınıflarında tek tek tablolarda yer alan özellikleri tanıtmak zorunda kalır ve bu özelliklere ilişkin verilen/alınan değerlerini de ayrıca elimiz yardımı ile girmek zorunda kalırdık. Bu işlem esnasında birçok sorunla da karşılaşmamız mümkündü. Biraz önce uygulamış olduğumuz yöntem sayesinde bize zaman kaybettiren birçok kodu yazmaktan kurtulabiliriz. Fakat aklınıza güvenli mi veya doğru mu oluşturuldu biçiminde sorular takılabilir. Bunun cevabı eper ekstra işlem yapmayacaksak doğru ve güvenilirdir. Fakat tablolar arası join gibi işlemler yapmak istersek tabii ki de otomatik olarak oluşturulan kodu düzenlememiz gerekecektir.

Join iÅŸlemlerini neden örnek verdiÄŸimize gelirse. SQL de join iÅŸlemleri birçok tablodan alınan deÄŸerler sonucunda bize sonuçlar döndürebilmekteydi. Bu tür iÅŸlemleri sql kodları ile yapmak kolaydı. Çünkü herhangi bir sınıftan veya baÅŸka bir yerden özellik çağırmadan sql kodları ile iÅŸlemlerimizi yapabiliyorduk. Fakat Model katmanında tabloları ayrı ayrı parçalı sınıflar biçiminde tuttuÄŸumuz için ve benzer isimli sütunlarda oluÅŸabileceÄŸi için sorgulama iÅŸlemlerimizde sorunlar çıkabilmekteydi. Bu sorunların kaldırılması içinde model katmanda oluÅŸturmuÅŸ olduÄŸumuz sınıflara o kullanacak olduÄŸumuz sütunlara iliÅŸkin özellikleri tanımlamalı ve iÅŸlemlerimize öyle devam etmeliydik. Ä°ÅŸte bizimde ÅŸu anda oluÅŸturmuÅŸ olduÄŸumuz dbml ‘in arka planındaki kodlar en basit biçimiyle oluÅŸturulmaktadır. Bizler onu özelleÅŸtirmek istersek buna imkan tanınmıştır.

C#
[System.Data.Linq.Mapping.DatabaseAttribute(Name="AdventureWorks")]
public partial class AdventureWorkDataContext : System.Data.Linq.DataContext
{

private static System.Data.Linq.Mapping.MappingSource mappingSource = new AttributeMappingSource();

#region Extensibility Method Definitions
//SQL ile yapılabilecek işlemler otomatik olarak tanımlandı
partial void OnCreated();
partial void InsertProduct(Product instance);
partial void UpdateProduct(Product instance);
partial void DeleteProduct(Product instance);
partial void InsertPurchaseOrderDetail(PurchaseOrderDetail instance);
partial void UpdatePurchaseOrderDetail(PurchaseOrderDetail instance);
partial void DeletePurchaseOrderDetail(PurchaseOrderDetail instance);
partial void InsertProductCategory(ProductCategory instance);
partial void UpdateProductCategory(ProductCategory instance);
partial void DeleteProductCategory(ProductCategory instance);
#endregion

-----------------------
//Product tablosuna ait parçalı sınıfa bakarsak
-----------------------

//Product tablosuna ilişkin özellikler ve değerleri
[Table(Name="Production.Product")]
public partial class Product : INotifyPropertyChanging, INotifyPropertyChanged
{

private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);

private int _ProductID;
private string _Name;
private string _ProductNumber;
private bool _MakeFlag;
private bool _FinishedGoodsFlag;
private string _Color;
private short _SafetyStockLevel;
private short _ReorderPoint;
private decimal _StandardCost;
private decimal _ListPrice;
private string _Size;
private string _SizeUnitMeasureCode;
private string _WeightUnitMeasureCode;
private System.Nullable<decimal> _Weight;
private int _DaysToManufacture;
private string _ProductLine;
private string _Class;
private string _Style;
private System.Nullable<int> _ProductSubcategoryID;
private System.Nullable<int> _ProductModelID;
private System.DateTime _SellStartDate;
private System.Nullable<System.DateTime> _SellEndDate;
private System.Nullable<System.DateTime> _DiscontinuedDate;
private System.Guid _rowguid;
private System.DateTime _ModifiedDate;
private EntitySet<PurchaseOrderDetail> _PurchaseOrderDetails;
#region Extensibility Method Definitions

//Listenin bir kısmıdır. Aslında birçok metot bulunmaktadır.
partial void OnLoaded();
partial void OnValidate(System.Data.Linq.ChangeAction action);
partial void OnCreated();
partial void OnProductIDChanging(int value);
partial void OnProductIDChanged();
partial void OnStandardCostChanged();
partial void OnListPriceChanging(decimal value);
partial void OnListPriceChanged();
partial void OnSizeChanging(string value);
#endregion

public Product()
{
this._PurchaseOrderDetails = new EntitySet<PurchaseOrderDetail>(new Action<PurchaseOrderDetail>(this.attach_PurchaseOrderDetails) , new Action<PurchaseOrderDetail>(this.detach_PurchaseOrderDetails));
OnCreated();
}

[Column(Storage="_ProductID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
public int ProductID
{
get
{
return this._ProductID;
}
set
{
if ((this._ProductID != value))
{
this.OnProductIDChanging(value);
this.SendPropertyChanging();
this._ProductID = value;
this.SendPropertyChanged("ProductID");
this.OnProductIDChanged();
}
}
}

[Column(Storage="_Name", DbType="NVarChar(50) NOT NULL", CanBeNull=false)]
public string Name
{
get
{
return this._Name;
}
set
{
if ((this._Name != value))
{
this.OnNameChanging(value);
this.SendPropertyChanging();
this._Name = value;
this.SendPropertyChanged("Name");
this.OnNameChanged();
}
}
}

//Özelliklere ilişkin metotlar devam etmektedir...

dbml ‘in kod bloÄŸu yukarda ki gibidir. Bu kod bloÄŸunda yalnızca Product tablosu deÄŸil diÄŸer eklemiÅŸ olduÄŸumuz tablolarda bulunmaktadır.

Şimdi yapmamız gereken model içerisine eklemiş olduğumuz tablolara ilişkin verileri Controller üzerinden çağırarak kullanmaktır. Bu işlemi yapabilmemiz için bir parçalı sınıf oluşturmalı ve oluşturmuş olduğumuz bu sınıfı ControllerAction yardımı ile çağırılabilir bir biçime dönüştürmeliyizdir. Ayrıca oluşturmuş olduğumuz parçalı sınıfın içersinde de yapacağımız işlemleri list içerisinde belirlememiz gerekmektedir.

Sınıfımızı oluşturmaya başladığımızda uygulamamızda oluşturulmuş olan isim alanlarına ulaşmak istediğimizde uygulamaismi. dememiz yeterli olacaktır.



Karşımıza çıkan isim alanları listesinden Models ‘ı seçtikten sonra karşımıza dört farklı seçebileceÄŸimiz sınıf çıkacaktır. Bunlardan üçü bizim eklediÄŸimiz tabloları temsil etmektedir. Dördüncüsü ile veri içeriÄŸini temsil etmektedir. Bu veri içeriÄŸi dbml dosyamızda oluÅŸturulmuÅŸ olan sınıfın içerisinden bir tiptir. İçeriÄŸe eriÅŸmek için kullanmakta yarar vardır.



Veri içeriğini tanımladıktan sonra ayrıntılarını görmek istediğimizde, tabloları LinQ içerisinde belirlenmiş olduğunu görürüz.



Daha sonra yapacağımız iÅŸlem ise çağıracak olduÄŸumuz tablonun görülebilmesi için RenderView üyesinin içerisinde tanımlayarak Controller ‘a istek geldiÄŸinde anlayabilmesine olanak tanımaktadır. Bu isteÄŸi algılayabilmesi de alınan deÄŸer ve deÄŸere iliÅŸkin tablo biçimin kod bloÄŸunda yazılması gerekmektedir.



Hazırlıklarımızı tamamladığımıza göre normal olarak uygulamamızı çalıştırdığımızda sorunsuz bir biçimde derlenmesi ve işlemesi gerekmektedir.

Uygulamamız sorunsuz bir biçimde derlendi ve web sayfamız karşımıza geldi. Åžimdi ise bizden istek yapmamızı beklemektedir. Normal zamanlarda form üzeriden sayfaya istek yaptığımızda View ‘ın içerisinde olan sayfaları çağırmaya çalışacaktır.

Bizde oluşturmuş olduğumuz list öğesini çağırmak için tarayıcımızın adres çubuğunu http://localhost:49170/Home/List yazıyoruz. Bu yazdığımız adrese göre tarayıcımız isteğini yapacak ve Controller da bu istek doğrultusunda gerekli olan sayfayı çağıracaktır.

Fakat her şey düşündüğümüz gibi olmuyor ve aşağıdaki hatayı alıyoruz.



KarşılaÅŸtığımız hataya dikkat ettiyseniz Products.aspx sayfası bulunamadı diyor. Fakat bu Products.aspx ‘i neden arıyor? Biz internet tarayıcımızın adres çubuÄŸuna home/List ‘i çağırmasını istemiÅŸtik. Bunun sebebi Controller içerisinde hazırlamış olduÄŸumuz list member ‘inin içerisinde eÄŸer kullanıcıdan böyle bir istek gelirse adı Product olan sayfaya yönlendirmesini istemiÅŸtik. O da görevini yaparak View/Home klasörünün altında Products.aspx ‘i aramaktadır. Fakat biz öyle bir sayfa eklemediÄŸimiz için bulamamaktadır.

O zaman bizde Products.aspx sayfasını ekleyelim ve sonucun nasıl olacağını görmeye çalışalım. Bu iÅŸlemi yapabilmemiz için View/Home klasörünün üzerinde Add/NewItem diyerek karşımıza ekleyebileceklerimizin listesini çıkartıyoruz. Bu listeden standart aspx sayfasını seçmek yerine MVC ‘den türetilecek olan MVCViewPage ‘i seçmek bizim iÅŸimizi kolaylaÅŸtıracaktır.



Sayfamızı ekledikten sonra içeriğine rastgele bir şeyler yazarak derlediğimiz zaman adres çubuğunda Home/List şeklinde bir çağırma olduğu dikkatimizden kaçmamaktadır.

Şimdi ise web sayfamızın içerisinden modelde tanımlanmış olanların hangilerine ve nasıl erişeceğimize göz atalım.

Temel asp bilgimizden <% %> bloklarının arasına kod yazılabildiÄŸini biliyoruz. Åžimdi web sayfamızda bu blokları kullanarak verileri göstertmeyi deneyelim. Bunun için yazmamız kod ViewData ‘dır. Bu kodu kullanmamız sonrasında intellisense ile karşımıza gelen sınıfların arasında veri içeriÄŸinin de olduÄŸunu görürüz.



Åžimdi ViewData ‘dan sonra alacağımız özellikleri, sınıfları v.b. diÄŸer bir çok ÅŸeyi Product ‘ın içerisinden almak istiyoruz. Bunu yapmak için, web sayfamızın kod tarafında hazır olarak oluÅŸturulmuÅŸ sınıfa generics (genel) tanımlayarak Product ‘taki bütün verileri almasını saÄŸlayabiliriz. Bunu yapabilmek için aÅŸağıdaki gibi bir kod oluÅŸturmamız gerekmektedir.

Alınabilecek değerler,



Bu görünebilir veri deÄŸerine Product yazıpta uygulamamızı derledikten sonra web sayfamızın içeriÄŸinden olan ViewData ‘nın intellisence ile bize getirecekleri aÅŸağıdaki gibi olacaktır.



ViewData ‘nın içerisinde karşımıza çıkan bu properties ‘lerin içeriklerini görmek istersek yapmamız gereken iÅŸlem kod tarafında tanımlamış olduÄŸumuz Product ‘ı IEnumerable ‘ın içeriÄŸinde tanımlamak olacaktır.



Bu değişikliğin sonucunda ViewData ile intellisense kullandığımızda karşımıza extensionlar aşağıdaki gibidir.



Yapacağımız sıradaki iÅŸlem ise Product tablosunun altında yer alan ProductName ‘leri ekrana basmak olacaktır. Bunu yapabilmek için foreach kullanmamız yeterli olacaktır.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Products.aspx.cs" Inherits="AdventureWorkMerhaba.Views.Home.Products" %>
<%@ Import Namespace="AdventureWorkMerhaba.Models" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
</head>
<body>
<div>
hede... bu bir deneme sayfasidir
<ul>
<% foreach (Product p in ViewData)
{

%>
<li><%=p.Name%></li>

<% } %>
</ul>
</div>
</body>
</html>

Sayfamızı derlediğimiz zaman aldığımız sonuç oldukça iyidir. Bütün liste karşımızdadır.



Fakat bütün liste karşımızda olmasına raÄŸmen masterpage ‘in tasarımını almamıştır. Ona eriÅŸebilmek için ise index.aspx ‘in içerisinde yer alan MasterPageContainer ‘larını Product.aspx ‘e ekleyerek tasarımı kazanmasını saÄŸlayabiliriz.

Master page ‘imizi ekledikten sonra ise karşılaÅŸtığımız listenin daha ÅŸirin ve düzenli gözükebilmesi için css ‘imizin içerisinde yeni bir tasarım oluÅŸturalım. OluÅŸturacak olduÄŸumuz tasarım aÅŸağıdaki gibi olacaktır.



Bu hazırladığımız tasarım sonucunda ise derleme esnasında web sayfamız aşağıdaki gibi bir görünüme kavuşacaktır.



Bu makalemizde MVC Framework ‘ü ve LinQ to SQL ’i kullanarak verilere eriÅŸimi ve sayfada göstermeyi anlatmaya çalıştık. Bir sonraki makalemizde ise ID ‘ler aldığımız deÄŸerleri kullanarak güncelleme yapmayı ve silmeyi incelemeye çalışacağız.

Umarım yararlı olmuştur.

Uygulamanın kaynak kodlarına linkten erişebilirsiniz. Veri tabanı dosyası kaynak kodlarda değildir. SQL server örnek veritabanından erişebilmeniz mümkündür. Sizin örneği çalıştırabilmeniz için WebConfig dosyasında gerekli düzenlemeleri yapmanız gerekmektedir.

Yorum Gönder

1 Yorumlar

Unknown dedi ki…
MVC-Framework serisi tam bana göre, ilaç gibi geliyor ;)
Eline sağlık...
İyi çalışmalar...

Ad Code

Responsive Advertisement