Merhaba Arkadaşlar,
Bundan 2-3 sene önce, yani yazılım projelerine el atmadan, EntityFramework, CodeFirst hakkında bilgi sahibi olmadan önce, Ömer Faruk Taşkın hocamla veritabanı DDL sql tümcecikleri oluşturan classlar hakkında konuşurduk. Ben hep veritablosuna karşılık bir class(POCO) olmasını gerektiğini hayal ederdim(ORM), vakit olsa boyle bir namespace yazılabilir diye düşünürdüm.
Yakın geçmişte anladım ki, teknoloji çok hızlı ilerlemiş. Zaten bu ORM araçları vasıtasıyla oluyormuş. Microsoft un bununla ilgili bir çözüm üretmiş. Şimdi verirlerle oynamak ASP.NET, WCF,veya windows formlarında EnrityFrameworkü kullanarak herşeyi yapabiliyorun. İster modelden, ister veri tabanından, isterseniz POCO(Plain Old CLR Objects) classlar giderek bir model(edmx) hazırlayabiliryorsunuz. Neyse ben lafı uzatmak istemiyorum. Ben aşağıdaki code yapısıyla POCO classlar oluşturmaya çalıştım. Bu poco classa göre yazılım SQL tümcesi üretiyor ve tablo yapısını veri tabanında oluşturmakta. Bazı yerleri karışık oldu, bunu kabul ediyorum.. Kriterleri azaltığım halde, minimum bu kadar yazabildim. Her entity tipinin bir niteliğin olması zorunlu ve string veya int titpinden olduğu kabul edilmiştir, yoksa kod daha da uzayacaktı.
Tabii burada asıl anlatmak istedeğim konu Nitelik(Attribute) hazırlama ve kullanma..
Zaman buldukça bu kodları yazım sırasına göre düzenleyeceğim. açıklama satırlarını aradan çıkartıp daha anlaşılabilir yapacağım..
![](/IMAGES%2f2013%2f02%2f20.jpg.jpgx)
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Entity;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace NitelikHazirlama
{
class Program
{
static void Main(string[] args)
{
//aslında static de yapabiliriz diye düşünebilirsiniz. Fakat bir nitelik yazıyorsanız yazdığınız sınıfın başka bir sınıfa kalıt vermemesi gerekir.
//Bu run time hatalarına sebeb olabilir. çünkü niteliğinin içeriğinin bilmiyorsunuz. Sealed (mühürlü) yaptığım bir sınıfıda static yapamam. Zaten derleyici buna izin vermez.
olusturTablo ol = new olusturTablo(typeof(User));
ol.create();
//Nuget Concole den Install-Package EntityFramework -Version 5.0.0 yazarak Entity fraewrok 5.0 yüklüyorum..="Data Source=|DataDirectory|\aspnet.sdf"
//<connectionStrings>
// <add name="DefaultConnection" connectionString="Data Source=|DataDirectory|\veritabani.sdf" providerName="System.Data.SqlServerCe.4.0" />
//</connectionStrings>
Database db=null;
//db.Create();
db.ExecuteSqlCommand("crete table kul", 0);
//Type tip;
//tip = typeof(User);
//foreach (TabloAdiAttribute ta in (TabloAdiAttribute[])tip.GetCustomAttributes(typeof(TabloAdiAttribute), false))
//{
// Console.WriteLine(ta);
//}
//StringBuilder createTableQueryString = new StringBuilder();
//GerekliAttribute gA = ((GerekliAttribute[])(tip.GetProperties()[1]).GetCustomAttributes(typeof(GerekliAttribute), false))[0];
//foreach (PropertyInfo item in tip.GetProperties())
//{
// GerekliAttribute gA = ((GerekliAttribute[])item.GetCustomAttributes(typeof(GerekliAttribute), false))[0];
// bool gereklimi = gA.Gereklimi;
// int AlanLenght = gA.Max;
// Console.WriteLine(item);
// createTableQueryString.Append(item.Name);
// createTableQueryString.Append(item.Name);
//}
//Console.WriteLine(createTableQueryString);
//Console.WriteLine(gA );
}
}
sealed class olusturTablo
{
public olusturTablo(Type tip)
{
this.tip = tip;
}
Type tip;
public void create()
{
TabloAdiAttribute ta=((TabloAdiAttribute[])tip.GetCustomAttributes(typeof(TabloAdiAttribute),false))[0];
//burada tip bir çok attribute uygulabibileceği için ve geri dönüş değeri attribute oldugundan tipin
//TabloAdiAttrubete sini cast yaparak gelen dizi elemanın 0 indexli değer aldım. Başka bir attribute olmadığı için 0
string tabloAdi = ta.TabloAdi;
StringBuilder createTableQueryString = new StringBuilder();
//http://msdn.microsoft.com/en-us/library/system.reflection.aspx System.Reflection isim alanını projemize katıyoruz.
//ayrıca referans etmemize gerek yok, zaten mscorb runtime da.
// artık aşağıda sql tümcesi biraz karışık oldı ve acemice oldu ama ne yapalım..
// Aşağıda kontroller her entity tipinin bit niteliğin olması zorunlu ve string ve int olarak kabul edilmiştir..
// yoksa kod daha da uzayacaktı..
createTableQueryString.Append("create table ");
createTableQueryString.Append(tabloAdi +",");
//tipimizin property memberlarını reflection yontemi ile dongu içinde alıp, bu propety lerin attributelerini elde ediyoruz.
foreach (PropertyInfo item in tip.GetProperties())
{
GerekliAttribute gA = ((GerekliAttribute[])item.GetCustomAttributes(typeof(GerekliAttribute), false))[0];
createTableQueryString.Append(" " + item.Name);
//object alantipi = item.GetValue(this, null);
if ((item.PropertyType.Name == "String") && (gA.Max != 0))
createTableQueryString.Append(" nvarchar(" + gA.Max.ToString() + ")");
else if ((item.PropertyType.Name == "String") && (gA.Max != 0))
createTableQueryString.Append(" nvarchar()");
else
createTableQueryString.Append(" int");
if (!gA.Gereklimi)
createTableQueryString.Append(" NOT NULL");
createTableQueryString.Append(",");
}
createTableQueryString.Remove(createTableQueryString.Length - 1, 1); //son virgülü kaldırdım..
Console.WriteLine(createTableQueryString);
}
}
[TabloAdi("Kullanici")]
class User
{
[Gerekli()]
public int id { get; set; }
[Gerekli()]
public string Ad { get; set; }
[Gerekli(false)]
public string Soyad { get; set; }
[Gerekli(false, 23)]
public string BabaAdi { get; set; }
}
//Attribute' lerin amacı, belkide en önemli özelliği, üretilen assembly içerisinde yer alan tip ve üyelere ekstra bilgiler katabilmeleridir.
//Bir başka deyişle metadata içerisine ilave bilgiler eklenebilmesini sağlamaktadır. Attribute lerden türemek zordundadır
//.Ben Attribute ve çift taba basarak hazırlamak istedim. Senaryo gereği tablo adını ve gerekli nitelik hazırlayan bir
//sql tümcesi hazırlamak için kullanacağım. TabloAdiAttribute class' a gerekli lik olanını ise metoda uygulamak istiyorum..
//Attributeler reflection (yansıma) dediğimiz olayın ta kendisini kullanırlar. Yanii kendi kodlarını assemly ye eklerler. Tabii ki run time da(var oluş amacı).
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
sealed class TabloAdiAttribute : Attribute
{
// See the attribute guidelines at
// http://go.microsoft.com/fwlink/?LinkId=85236
readonly string tabloAdi;
static int sayisi=0;
public TabloAdiAttribute()
: this("Adsiz"+sayisi.ToString())
{
sayisi++;
}
public TabloAdiAttribute(string tabloAdi)
{
this.tabloAdi = tabloAdi;
// TODO: Implement code here
//throw new NotImplementedException();
}
public string TabloAdi
{
get { return tabloAdi; }
}
public int NamedInt { get; set; }
}
//method için.
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
sealed class GerekliAttribute : Attribute
{
readonly bool gereklimi;
readonly int max;
public int Max
{
get { return max; }
}
public GerekliAttribute()
:this(true)
{
//varsayılan olarak true yapıyorum.
//Tıpkı entiyFrameWrok de kullanılan Convention Kurallarında olduğu gibi.
// ben de bir nevi convention rule yaptım yani :)
// buradan covention hakkıında bir fikir sahibi olabilirisniz. http://blogs.msdn.com/b/efdesign/archive/2010/06/01/conventions-for-code-first.aspx
// Buradan ise Entity bir tip Yani POCO (Plain Old CLR Objects) claslarımızı oluştururken Conventions Rules classlarını inceleyebilirisiniz.
//http://msdn.microsoft.com/en-us/library/gg696316(v=vs.103).aspx
//
}
public bool Gereklimi
{
get { return gereklimi; }
}
// This is a positional argument
public GerekliAttribute(bool gereklimiAcaba)
:this(gereklimiAcaba,255)
{
//this.gereklimi = gereklimiAcaba;
// TODO: Implement code here
//throw new NotImplementedException();
}
public GerekliAttribute(bool gereklimiAcaba, int max)
{
this.gereklimi = gereklimiAcaba;
this.max= max;
// TODO: Implement code here
//throw new NotImplementedException();
}
//Burası argument vermek için.
public int NamedInt { get; set; }
}
}