20 Aralık 2011 Salı

C# sealed Anahtar Sözcüğü

Nesne yönelimli programlamanın temel felsefelerinden biri de kalıtımdır. Konu ile ilgili detayları şuradan inceleyebilirsiniz. sealed, sınıflara ve üyelere(metot ve property) uygulanabilen bir anahtar sözcüktür. Anlamı; kapalı, mühürlü şeklinde çevirilebilir. Sınıflar için kalıtımı, üyeler için ise override edilmeyi önler. Basit örnekler üzerinden inceleme yapalım.

Birbirinden türetilen A,B ve C sınıfları olsun.

class Program : C

    {

        static void Main(string[] args)

        {

 

        }

    }

  

    public class A

    {

        public string AProperty { get; set; }

    }

 

    public class B : A

    {

        public string BProperty { get; set; }

 

    }

 

    public class C : B

    {

        public string CProperty { get; set; }

    }

Main metodu içerisinde Program tipinden bir nesne örneklediğimizde, Program sınıfının C sınıfından kalıtılması sebebiyle ilgili property’lere erişebildiğimizi görürüz. Zaten kalıtımın temel mantıklarından biri de buydu.

image

Projeyi yukarıdaki hali ile derlediğimizde herhangi bir hata almayacağız. Şimdi de amacımız, C sınıfından yapılacak bir kalıtımı önlemek. Bunun için C sınıfına sealed anahtar sözcüğünü uygulamamız yeterli olacaktır.

public sealed class C : B

    {

        public string CProperty { get; set; }

    }

sealed ile, C sınıfından herhangi bir kalıtım yapılması halinde derleme zamanı hatası alınmasını sağladık. Son hali ile projemizi derlediğimizde aşağıdaki gibi bir hata mesajı ile karşılaşacağız.

'sealedKeyword.Program': cannot derive from sealed type 'sealedKeyword.C'

Program sınıfının, sealed olarak işaretlenmiş olan C sınıfından kalıtamayacağı mesajı aldık. Dolayısı ile artık C sınıfından kalıtım yapamayacağız.

Şimdi de A sınıfı içerisine virtual bir metot ekleyelim. Daha sonra da B sınıfında bu metodu override edelim.

public class A

  {

      public virtual void Test()

      {

          Console.WriteLine("A sınıfındaki Test metodu çalıştı");

      }

  }

 

public class B : A

  {

      public override void Test()

      {

          Console.WriteLine("B sınıfındaki Test metodu çalıştı");

      }

  }

Program sınıfını B sınıfından kalıtalım ve Test metodunu override etmeye çalışalım.

image

Görüldüğü gibi Test metodu da override edilebilir bir metot olarak karşımıza çıktı.

class Program : B

    {

        public override void Test()

        {

            Console.WriteLine("Program sınıfındaki Test metodu çalıştı");

        }

 

        static void Main(string[] args)

        {

 

        }

    }

Programı derlediğimizde hata ile karşılaşmayacağız. Şimdi de B sınıfına giderek Test metodumuzu sealed olarak işaretleyelim.

public class A

  {

      public virtual void Test()

      {

          Console.WriteLine("A sınıfındaki Test metodu çalıştı");

      }

  }

 

public class B : A

  {

      public sealed override void Test()

      {

          Console.WriteLine("B sınıfındaki Test metodu çalıştı");

      }

  }

Tekrar program sınıfına dönelim ve Test metodunu override etmeyi deneyelim.

image

Artık override edilebilecek üyeler listesinde Test metodunu göremeyeceğiz. Sebebi, sealed ile işaretlenmiş olması, yani artık override edilemeyecek olmasıdır. Derleyiciden yardım almayarak manuel olarak override ettiğimizde ise derleyici tarafından bir hata mesajı alacağız.

class Program : B

    {

        public override void Test()

        {

            Console.WriteLine("Program sınıfındaki Test metodu çalıştı");

        }

 

        static void Main(string[] args)

        {

 

        }

    }

Programı derlediğimizde alacağımız hata mesajı aşağıdaki gibi olacaktır.

'sealedKeyword.Program.Test()': cannot override inherited member 'sealedKeyword.B.Test()' because it is sealed

Framework içerisinden örnek vermek gerekirse; string tipi de sealed olarak işaretlenmiştir. Yani string tipinden kalıtım yapamayız.

Untitled



15 Aralık 2011 Perşembe

SQL Cursor Kullanımı

C# dilinin syntax’ından (özellikle visual studio’nun da yardımları ile) sonra T-SQL çoğumuz için kabus gibi gelebilir. Ancak zamanla bu ön yargının kırıldığını söyleyebilirim. Nitekim benim için böyle oldu Smile. Bugün SQL’de çok da fazla sevilmeyen cursor konusunu inceleyeceğiz. Çoğu programlama dilinde görmeye alıştığımız for döngüsü ile aynı işlevdedir aslında. Cursor’lar Kayıtlara satır satır erişmemize imkan sağlar. Cursor tanımlarken içerisinde döneceği bir select ifadesi yazarız ve her bir turda elde edilen değerler için bir takım işlemler yaparız.

AdventureWorks veri tabanındaki Product tablosunda bulunan ürünlerin fiyatlarını ele alalım. Fiyatı 0 ise “bedava”, 1-1000 arasında ise “ucuz”, 1000’den fazla ise “pahalı” ifadelerini ekrana yazdıralım.

DECLARE  @Result TABLE --Sonuç kümesini tutacağımız bir tablo tanımladık

(

      Name NVARCHAR(50),

      Durum NVARCHAR(10)

)

 

DECLARE cr_Read CURSOR FOR

      SELECT Name,ListPrice FROM Production.Product --cursor'un gezeceği sorgu. Her satır için ad ve fiyat bilgisini elde edeceğiz.

    

DECLARE @name NVARCHAR(50), @listprice MONEY --döngünün her satır için tuttuğu değerleri atamak için değişkenler tanımladık. Select ifadesinde elde ettiğimiz isim ve fiyat değerlerini bu değişkenlere atayacağız.

 

OPEN cr_Read --SqlConnection kullanırken bağlantı açmak gibi düşünülebilir. (conn.Open() gibi)

 

 

FETCH NEXT FROM cr_Read INTO @name, @listprice  --Her bir satır için dönmesini sağlayan komut

--ya da " FETCH cr_Read INTO @name, @listprice "  şeklinde yazılabilir.

 

WHILE @@FETCH_STATUS=0 --Satırdan değer gelip gelmediğini kontrol ediyoruz. 0 ise Name ve ListPrice kolonlarından değer gelmiş demektir.

 

      BEGIN

                      

            DECLARE @durum NVARCHAR(20)

            IF(@listprice=0)

                  BEGIN

                        SET @durum='Bedava'

                  END

            ELSE IF(@listprice<1000)

                  BEGIN

                        SET @durum='Ucuz'

                  END

            ELSE

                  BEGIN

                        SET @durum='Pahalý'

                  END

          

            INSERT INTO @Result VALUES(@name,@durum)

          

            FETCH NEXT FROM cr_Read INTO @name, @listprice --her bir satır için dönülecek sorguyu tekrar ediyoruz. Çünkü veriye erişim yapıldıktan sonra döngüye girilmektedir.

      END

 

CLOSE cr_Read --cursor’un içerdiği sonuç kümesi boşaltılır.

DEALLOCATE cr_Read --cursor’a erişimi engeller ve belleği temizler. Bu komutu yazmassak cr_Read ismind başka bir cursor tanımlayamayız çünkü hafızada açılan yer kullanımda kalır.

 

SELECT * FROM @Result --sonuç kümesini görüntülüyoruz.

image

 



Serinin önceki bölümlerinde döküman okuma ve döküman güncelleme kısımlarını ele almıştık. Bugün de linq to xml ile döküman oluşturacağız.

Bir console uygulaması açarak basit bir örnek ile konuyu ele almaya başlayalım. Koordinat adında kök elementimiz olsun, içerisinde de Nokta adında elementler olsun ve her nokta içerisinde X, Y ve Z isminde child elementler tanımlayalım. İşlemi yapmaya bir döküman oluşturarak başlayacağız. Ardından bu döküman üzerine elementlerimizi ekleyeceğiz ve son adım olarak da dökümanı kaydedeceğiz.

class Program

    {

        static void Main(string[] args)

        {

            XDocument dokuman = new XDocument();

 

            dokuman.Add(

                new XElement("Koordinat", //root element

                    new XElement("Nokta", //child element

                        new XElement("X", 2),

                        new XElement("Y", 5),

                        new XElement("Z", -1)),

                    new XElement("Nokta",

                        new XElement("X", 0),

                        new XElement("Y", 0),

                        new XElement("Z", 0)),

                    new XElement("Nokta",

                        new XElement("X", -2),

                        new XElement("Y", 1),

                        new XElement("Z", 4))));

 

            dokuman.Save("Koordinatlar.xml");

 

        }

    }

oluşturduğumuz döküman exe’nin içinde bulunduğu klasöre, yani debug içerisine kaydedilecektir. Projemize sağ tuş tıklayarak “open folder in windows explorer” seçeniğne tıklayarak projemizin klasörüne gidebilir, buradan da bin –> debug klasörü içerisinde oluşturduğumuz xml dökümanını görebiliriz.

image

Bu işlemi direk olarak XElement tipi üzerinden de gerçekleştirmek mümkündür. Tek satırda döküman oluşturmak için bir XElement örnekleyerek içerisine child elementleri tanımlayabilir ve yine bu XEelement üzerinden Save metodunu çağırabiliriz.

class Program

    {

        static void Main(string[] args)

        {

            new XElement("Koordinat", //root element

                new XElement("Nokta", //child element

                    new XElement("X", 2),

                    new XElement("Y", 5),

                    new XElement("Z", -1)),

                new XElement("Nokta",

                    new XElement("X", 0),

                    new XElement("Y", 0),

                    new XElement("Z", 0)),

                new XElement("Nokta",

                    new XElement("X", -2),

                    new XElement("Y", 1),

                    new XElement("Z", 4))).Save("Koordinatlar2.xml");

        }

    }

 

image

Bir başka örnek üzerinden ilerleyelim. Sayilar adında bir döküman oluşturalım. İçerisinde Sayi adında child elementler olsun ve her element içerisinde sayının değerini, karesini ve küpünü göstermeye çalışalım. Bir de nitelik ekleyerek sayının asal olup olmama durumunu gösterelim.

class Program

    {

        static void Main(string[] args)

        {

            new XElement("Sayilar",

                new XElement("Sayi",

                    new XAttribute("AsalMi", true),

                    new XElement("Değeri", 5),

                    new XElement("Karesi", 25),

                    new XElement("Küpü", 125)),

                new XElement("Sayi",

                    new XAttribute("AsalMi", false),

                    new XElement("Değeri", 8),

                    new XElement("Karesi", 64),

                    new XElement("Küpü", 512))).Save("Sayilar.xml");

        }

    }

image

Şimdi de oluşturacağımız döküman için kullanacağımız dataların bir veri tabanından geldiğini düşünelim. Bunun için projemize bir Entity Data Model ekleyelim. (AdventureWorks veri tabanını kullanarak ilerliyor olacağım) Amacımız, Product tablosundaki en pahalı 5 ürünün adını ve kategori adını xml formatında yazdırmak olacak.

class Program

    {

        static void Main(string[] args)

        {

            AdventureWorksEntities context = new AdventureWorksEntities();

 

            new XElement("Urunler",

                context.Product.OrderByDescending(p => p.ListPrice).Take(5).ToList().Select(urun =>

                    new XElement("Urun",

                        new XElement("UrunAd", urun.Name),

                        new XElement("Kategori", urun.ProductSubcategory.ProductCategory.Name)))).Save("urunler.xml");          

 

        }

    }

image

Bir başka örnek ile devam edelim. ProductSubCategory tablosundaki ilk 5 alt kategoriyi çekerek isimlerini ve bu isimlere bağlı ilk 5 ürünü xml formatta oluşturmaya çalışalım.

class Program

    {

        static void Main(string[] args)

        {

            AdventureWorksEntities context = new AdventureWorksEntities();

 

            new XElement("Urunler",

                context.ProductSubcategory.Take(5).ToList().Select(sub =>

                    new XElement(sub.Name.Replace(" ", string.Empty),

                        sub.Product.Take(5).ToList().Select(urun =>

                            new XElement("Urun",

                                new XElement("Ad", urun.Name),

                                new XElement("Fiyat", (int)urun.ListPrice)))))).Save("urunler2.xml");

 

        }

    }

Burada alt kategori isimlerini yazdırırken Replace metodunu kullandık. Çünkü gelen alt kategori isimleri boşluklar içermektedir. Xml elementi tanımlarken boşluk kullanamayız. Oluşturduğumuz döküman aşağıdaki gibidir.

image

Yukarıdaki örneği bir üst seviyeye çıkaralım. İlk olarak Kategori isimlerinden elementler oluşturalım. Daha sonra bu kategorilere bağlı ilk 5 alt kategori ve bu alt kategorilere bağlı ilk 5 ürünü xml formatta bir dökümana kaydedelim.

class Program

    {

        static void Main(string[] args)

        {

            AdventureWorksEntities context = new AdventureWorksEntities();

 

            new XElement("Urunler",

                context.ProductCategory.ToList().Select(category =>

                    new XElement(category.Name,

                        category.ProductSubcategory.Take(5).ToList().Select(subCategory =>

                            new XElement(subCategory.Name.Replace(" ", string.Empty),

                                subCategory.Product.Take(5).ToList().Select(product =>

                                    new XElement("Urun",

                                        new XElement("Ad", product.Name)))))))).Save("urunler3.xml");

 

        }

    }

image

Şimdi de bir html dökümanı oluşturmaya çalışalım. Bir tablo oluşturarak ürünlerin id, ad ve fiyat bilgilerini görüntüleyelim.

class Program

    {

        static void Main(string[] args)

        {

            AdventureWorksEntities context = new AdventureWorksEntities();

 

            new XElement("html",

                new XElement("head",

                    new XElement("title", string.Format("{0} tarihinde LINQ to XML ile dinamik olarak üretildi.", DateTime.Now))),

                new XElement("body",

                    new XElement("table",

                        new XAttribute("border", 1),

                        new XElement("tr",

                            new XElement("td", "ID"),

                            new XElement("td", "Ad"),

                            new XElement("td", "Fiyat")),

                        new AdventureWorksEntities().Product.OrderByDescending(p => p.ListPrice).Take(10).ToList().Select(p =>

                            new XElement("tr",

                                new XElement("td", p.ProductID),

                                new XElement("td", p.Name),

                                new XElement("td", p.ListPrice.ToString())))))).Save("Anasayfa.html");

 

        }

    }

NOT: Bir dosyanın uzantısı o dosyanın tipini belirtmez. Çift tıklandığında hangi program ile açılacağını belirtir.

Oluşan dökümanı browserda açalım. Aşağıdaki gibi bir görüntü ile karşılaşacağız.

image