logo


Welcome Guest! To enable all features please Giriş or Kayıt.

Bildirim

Icon
Error

Ayarlar
Son mesaja git Go to first unread
bilgehanyildiz  
#1 Gönderildi : 25 Şubat 2015 Çarşamba 10:04:54(UTC)
bilgehanyildiz

Sıralama: Member

Gruplar: Registered
Katılan: 25.02.2015(UTC)
Mesajlar: 12
Turkey
Konum: İstanbul

2 Mesajına Toplam 2 Kere Teşekkür Edildi.
C# da runtimeda tip bilgilerine erişebilmemize yarar.Kütüphane olarak System.Reflection namespace altındadır

Reflection ile runtimeda classın fieldların,propertilerin özelliklerine vs erişebilir ve ona göre işlemler yapabiliriz.ORM araçlarının temel mantığıda bunun üstüne kuruludur.

Örnek olarak veritabanımızdaki bir tablonun nesne olarak modellemesini yapalım

Kod:

public class CustomerEntity :
    {

        private int _CustomerID;

        private string _Name;

        private string _Surname;

	  private DateTime? _BirthDate;

  	  [EntityPrimaryKey]
        public int CustomerID
        {
            get
            {
                return _CustomerID;
            }

        }

        public string Name
        {
            get
            {
                return _Name;
            }
            set
            {
                _Name = value;
            }
        }

        public  string Surname
        {
            get
            {
                return _Surname;
            }
            set
            {
                _Surname = value;
            }
        }

public DateTime? BirthDate
        {
            get
            {
                return _BirthDate;
            }
            set
            {
                _BirthDate = value;
            }
        }
}





Görüldüğü gibi Veritabanımda CustomerID,Name,Surname,BirthDate olarak var olan 4 alanın kod tarafında nesne olarak modellemesini yaptım.Bunlardan CustomerID nin bir CustomAttribute ile primary Key olduğunu belirttim.Tablomun adıda Customer olsun.

Not:C# da Custom Attribute Tanımlama,yapmanız gereken sadece AttributeUsage Attribute kısmını sınıfın üstüne yazmak ve Sınıfınızın Attributedan türemesini sağlamaktır.Bu sayede artık biz de kendi kullanımımıza göre bir Attribute yaratmış olduk

Kod:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 
   public class EntityPrimaryKey:Attribute
    {
    }



Benim senaryoma göre CustomerID de otomatik artan ve integer olsun

Formda butonun arkasına

Kod:

CustomerEntity b = new CustomerEntity();     
       b.Name = "Bilgehan";
       b.Surname = "Yıldız";
 int a= EntityProcess<CustomerEntity>.Save(b);



yukarıdaki gibi kodumuzu yazalım.Ve EntityProcess sınıfımıza gelerek sınıfımızı oluşturalım.Ben yine ORM araçlarındaki gibi dinamik bir Save metodu yapmak istiyorum bunun için sınıfımı aşağıdaki gibi tanımlıyorum.Bu şekilde artık sınıfım generic olarak benim nesnelerimi alabilecek hale geliyor

Kod:

public class EntityProcess<TEntity> where TEntity : class, new()


    public static int Save(TEntity entity)
        {

PropertyInfo[] properties = typeof(TEntity).GetProperties();




PropertyInfo ile Oluşturduğum Sınıfımın typeof(TEntity).GetProperties(); ile tüm propertylerini bir diziye alıyorum.Burada Tentity yerine üst katmandan çağırdığımızda CustomerEntity dolduruyor ve böylece dinamik olarak CustomerEntity classın içerisindeki propertylere ulaşabiliyoruz


Kod:

foreach (PropertyInfo p in properties)
{

//Aşağıdaki komut ilede eğer gelen propertimin PrimaryKey Attribute varsa insert queryimize eklemiyoruz
if (p.GetCustomAttributes(typeof(EntityPrimaryKey), false).Count() <= 0)

 { 
//Get Value ilede metoda gönderdiğimiz nesnedeki propertylerin değerini okuyabiliyoruz.örnek CustomerEntity de Name propertsini Bilgehan olarak setlemiştik.Aşapıdaki kodla Bilgehan değerini okuruz
object columnValue = p.GetValue(entity, null);
                  if (columnValue != null)
                  {



Gene Reflection yardımı ile bulabileceğimiz şeylerden birede propertyimizin Int mi,String mi olduğu,nullable olup olmadığı gibi kavramlardır

Mesela BirthDate i nullable olarak tanımlamıştık.Bir kolon nullable ise hangi tipte olduğunu bulmak için önce birinci ifteki gibi GetGenericTypeDefinition() ile nullable olup olmadığını kontrol etmeliyiz.

Ondan sonra ise ikinci ifteki gibi p.PropertyType.GetGenericArguments()[0].Name ilede tipini kontrol edebiliyoruz.

Kod:

if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
           {
               if (p.PropertyType.GetGenericArguments()[0].Name == "Int32")
               {
                   return SqlDbType.Int;
               }



Eğer propertyimiz nullable değilse aşağıdaki gibi kontroller yapabiliriz
PropertyType.Name demek yeterli oluyor

Kod:

if (p.PropertyType.Name == "Int32")
               {
                   return SqlDbType.Int;
               }



Son olarak genel olarak kodlarımıza göz atarsak TypeFinder benim yukarıda yazdığım şekilde propertnin Dbtype bulan bir sınıf.

Kod:

public class EntityProcess<TEntity> where TEntity : class, new()
    {
        public static int Save(TEntity entity)
        {
            EMDbManager db = new EMDbManager();
            PropertyInfo[] properties = typeof(TEntity).GetProperties();
            string insertSql = "insert into {0} ({1}) values({2});select scope_identity()";

            StringBuilder columnNames = new StringBuilder();
            StringBuilder parameterNames = new StringBuilder();
            SqlCommand cmd = new SqlCommand();

            foreach (PropertyInfo p in properties)
            {
                TypeFinder tp = new TypeFinder();
                //Eger gelen entity bizim custom attribute ID içermiyorsa
                //Otomatik Artan olmayan PrimaryKeyli yerlerde Custom PrimaryKey Attribute Olmayacak
                if (p.GetCustomAttributes(typeof(EntityPrimaryKey), false).Count() <= 0)
                {
                  object columnValue = p.GetValue(entity, null);
                  if (columnValue != null)
                  {
                      columnNames.Append(p.Name);
                      columnNames.Append(",");
                  
                      parameterNames.Append("@");
                      parameterNames.Append(p.Name);
                      parameterNames.Append(",");
                      cmd.Parameters.Add(new SqlParameter(p.Name, columnValue, tp.FindType(p)));
          
                  }
                }

            }
            insertSql = string.Format(insertSql, entity.GetType().Name.Replace("Entity", ""), columnNames.ToString().TrimEnd(','), parameterNames.ToString().TrimEnd(','));



En son string Format ile benim sınıfımın adı CustomerEntity entity kısmını replace yok ediyorum ve generic olarak bir insert cümlesi yukarıdaki gibi oluşturmuş oluyorum.


Bu konudaki kullanıcılar
Guest
Forumu Atla  
Bu foruma yeni konular postalayamazsınız.
Bu forumda ki konulara yeni posta gönderemezsiniz.
Bu forumdaki postalarınızı silemezsiniz.
Bu forumdaki postalarınızı düzenleyemezsiniz.
Bu forumda anketler yaratamazsınız.
Bu forumdaki anketlere oy veremezsiniz.