Makale Özeti

CodeSmith ile çalışırken en çok kullanıldığını söylediğimiz veritabanı şemasına erişebilme durumunda bahsedeceğiz.

Makale

CodeSmith - Veritabanı Şeması ile Çalışmak - 3

Delete,Insert ve Update gibi işlemler için tablonun primarykey veya primarykeylerini bilmemiz gereklidir.

CodeSmith Api referencedan görülebileceği gibi veritabanı tablosundaki Primary Key'ler i almak için TableSchema sınıfının PrimaryKey özelliği kullanılır.

TableSchema.PrimaryKey özelliği PrimaryKeySchema türündedir. Bu sınıfında MemberColumns özelliği vardır. Bu özellik ColumnSchemaCollection türündedir ve tablonun primary key veya primary keylerini temsil eden ColumnSchema türünde nesneler içerir.

Bir tablonun primarykeyi olan sütünlara erişmek için TableSchema.PrimaryKey.MemberColumns hiyerarşisini kullanmak gerekmektedir.

Not: Template ile oluşturacağımız temel stored procedureler update ve delete için tablo üzerindeki primarykey veya primarykeyleri kullanmak zorundadırlar.

Northwind veritabanını örnek olarak kullanarak her tablonun primarykey lerini listemek için aşağıdaki templatei yazın ve çalıştırın. (Bu örnek için Northwind i seçmemdeki sebep birden fazla sutündan oluşan primarykey lere sahip tablolar içermesidir.)

<%@ CodeTemplate Language="C#" TargetLanguage="Text" %>

<%@ Property Name="Veritabani" Type="DatabaseSchema" Optional="False" %>

<%@ Assembly Name="SchemaExplorer" %>

<%@ Import Namespace="SchemaExplorer" %>

 

<%@ Import Namespace="System.Text" %>

 

<script runat="template">

      void ListPrimaryKeys()

      {

            StringBuilder sb=new StringBuilder();

            foreach(TableSchema ts in Veritabani.Tables)

            {

                  Response.WriteLine(ts.Name);

                  Response.Indent();

                  ColumnSchemaCollection birinciller=ts.PrimaryKey.MemberColumns;

                  foreach (ColumnSchema c in birinciller)

                  {

                        Response.WriteLine(c.Name);

                  }

                  Response.Unindent();

            }

            Response.WriteLine(sb.ToString());

      }

</script>

<%

ListPrimaryKeys();

%>



ColumSchema ile sütunların veri türünü elde etmek

ColumSchema sınıfın SystemType özelliği sütun için .net framework üzerinde karşılık gelen veri türünü string olarak döner. NativeType özelliği ise sütunun veri türünü SQL Server üzerindeki veri türlerine göre döner. Aşağıdaki örneklerde gözükmektedir ki SQL Server üzerindeki int,.NET Framework de System.Int32 ye karşılık gelmekte, nchar ve nvarchar ise System.String'e karşılık gelmekte.

<script runat="template">

      void ListPrimaryKeys()

      {

            StringBuilder sb=new StringBuilder();

            foreach(TableSchema ts in Veritabani.Tables)

            {

                  Response.WriteLine(ts.Name);

                  Response.Indent();

                  ColumnSchemaCollection birinciller=ts.PrimaryKey.MemberColumns;

                  foreach (ColumnSchema c in birinciller)

                  {

                        Response.WriteLine(c.Name);

                        Response.Indent();

                        Response.WriteLine("SystemType : " +  c.SystemType);

                        Response.WriteLine("NativeType : " + c.NativeType);

                        Response.Unindent();

                  }

                  Response.Unindent();

            }

            Response.WriteLine(sb.ToString());

      }

</script>



Stored procedure oluştururken yukarıdaki verilen veri türlerinden NativeType özelliğinden dönen türleri kullanacağız. Ancak bu türler bu özellikten döndükleri gibi kullanılamazlar. Örneğin char veri türü için ilgili sütunun uzunluğunu öğrenmek gereklidir.

Bu gereksinim için template üzerinde aşağıdaki gibi bir metod ekleyerek düzenleme yapıyoruz.

<script runat="template">

public string GetNativeType(ColumnSchema column)

{

            string param = string.Empty;

            param=column.NativeType;

           

            switch (column.DataType)

            {

                  case DbType.Decimal:

                  {

                        param = column.NativeType + "(" + column.Precision + ", " + column.Scale + ")";

                        break;

                  }

                  case DbType.AnsiString:

                  case DbType.AnsiStringFixedLength:

                  case DbType.String:

                  case DbType.StringFixedLength:

                  {

                        if (column.NativeType != "text" && column.NativeType != "ntext")

                        {

                             if (column.Size > 0)

                             {

                                   param = column.NativeType + "(" + column.Size + ")";

                             }

                        }

                        break;

                  }

            }    

      return param;

}

      void ListPrimaryKeys()

      {

            StringBuilder sb=new StringBuilder();

            foreach(TableSchema ts in Veritabani.Tables)

            {

                  Response.WriteLine(ts.Name);

                  Response.Indent();

                  ColumnSchemaCollection birinciller=ts.PrimaryKey.MemberColumns;

                  foreach (ColumnSchema c in birinciller)

                  {

                        Response.WriteLine(c.Name);

                        Response.Indent();

                        Response.WriteLine("SystemType : " +  c.SystemType);

                        Response.WriteLine("NativeType : " + GetNativeType(c));

                        Response.Unindent();

                  }

                  Response.Unindent();

            }

            Response.WriteLine(sb.ToString());

      }

</script>



Templateimize GetNativeType adındaki metodu ekledik. Bu metod basit bir switch..case ifadesi ile veri türü yanında uzunluk belirtilmesi gerekli olan türleri tespit edip Size özelliği ile gerekli veriyi çıktıya ekliyor. Decimal veri türü için ise Precision ve Scale özelliklerini kullanıyoruz. Precision ile sayının kaç karakterden oluştuğunu, Scale ile ise ondalık bölümün kaç karakterden oluştuğunu öğreniyoruz. ListPrimaryKeys metodu içindeki en içteki  for döngüsü içinde NativeType'ı bastırırken GetNativeType metodunu çağırıp parametre olarak ColumSchema türündeki c nesnesini geçiyoruz.GetNativeType ise geriye string olarak SQL Server üzerinde veriyi temsil etmek için gerekli olan tanımlamayı dönüyor.

Delete işlevini gerçekleştiren stored procedure oluşturmak.

Delete işlemini yapmak için SELECT den farklı olan nokta tüm primarykey ler için parametre alan ve bunu sorgunun WHERE şartında kullanmamız olacaktır.

      public string GetSqlParam(ColumnSchema column)

      {

            string param = string.Empty;

            param=GetNativeType(column);

            param="@" + column.Name + " " + param;

            return param;

      }

Yukarıda bundan sonra yazacağımız stored procedure templateleri için tekrar kullanacağımız bir metod daha bulunuyor. GetSqlParam metodu parametre olarak ColumnSchema nesnesi alıyor ve kendi içinde GetNativeType metodunu da çağırarak stored procedure için gerekli olan paremetre tanımlamasını dönüyor. Örneğin @ad varchar(20)  gibi bir değer dönebilir.

<%@ CodeTemplate Language="C#" TargetLanguage="Text" %>

<%@ Property Name="Veritabani" Type="DatabaseSchema" Optional="False" %>

<%@ Assembly Name="SchemaExplorer" %>

<%@ Import Namespace="SchemaExplorer" %>

 

<%@ Import Namespace="System.Text" %>

 

<script runat="template">

      public string GetNativeType(ColumnSchema column)

      {

                  string param = string.Empty;

                  param=column.NativeType;

                 

                  switch (column.DataType)

                  {

                        case DbType.Decimal:

                        {

                             param = column.NativeType + "(" + column.Precision + ", " + column.Scale + ")";

                             break;

                        }

                        case DbType.AnsiString:

                        case DbType.AnsiStringFixedLength:

                        case DbType.String:

                        case DbType.StringFixedLength:

                        {

                             if (column.NativeType != "text" && column.NativeType != "ntext")

                             {

                                   if (column.Size > 0)

                                &n bsp;  {

                                &n bsp;        param = column.NativeType + "(" + column.Size + ")";

                                &n bsp;  }

                             }

                             break;

                        }

                  }    

            return param;

      }

      public string GetSqlParam(ColumnSchema column)

      {

            string param = string.Empty;

            param=GetNativeType(column);

            param="@" + column.Name + " " + param;

            return param;

      }

      void CreateDeleteSP()

      {

            StringBuilder sb=new StringBuilder();

            foreach(TableSchema ts in Veritabani.Tables)

            {

                  CreateDeleteSP(ts,sb);

            }

            Response.WriteLine(sb.ToString());

      }

      void CreateDeleteSP(TableSchema ts,StringBuilder eklenecekSB)

      {

            eklenecekSB.Append("CREATE PROC [" + ts.Name + "_DELETE]\n");

            for (int i=0;i<ts.PrimaryKey.MemberColumns.Count;i++)

            {

                  ColumnSchema c=ts.Columns[i];

                  eklenecekSB.Append(GetSqlParam(c));

                  if(i!=ts.PrimaryKey.MemberColumns.Count-1)

                  {

                        eklenecekSB.Append(",\n");

                  }

            }

            eklenecekSB.Append("\nAS");

            eklenecekSB.Append("\nDELETE FROM [" + ts.Name + "]");

            eklenecekSB.Append("\nWHERE ");

           

            for (int i=0;i<ts.PrimaryKey.MemberColumns.Count;i++)

            {

                  ColumnSchema c=ts.Columns[i];

                  eklenecekSB.Append(c.Name + "=@" + c.Name);

                  if(i!=ts.PrimaryKey.MemberColumns.Count-1)

                  {

                        eklenecekSB.Append(" AND ");

                  }

            }

            eklenecekSB.Append("\nGO\n\n");

      }

</script>

<%

CreateDeleteSP();

%>



 

CodeSmith ile bir sonraki makalemizde veritabanı şemasını SchemaExplorer ile okuyarak Insert ve Update işlevlerini yerinei getiren templateler oluşturacağız.
 

Cengiz HAN
cengiz@cengizhan.com
Microsoft ASP.NET Most Valuable Professional
MCSD.NET, MCT