28 Haziran 2011 Salı

SSMS 2008 - Saving changes is not permitted

Saving changes is not permitted. The changes you have made require the following tables to be dropped and re-created.” hatası SQL Server 2008 den sonra ortaya çıkan ve bizleri bir miktar bunaltan bir hata çeşididir. Çünkü hatanın çözümü için sizlere önerdiği yol değiştirmek istediğiniz tablonun yeniden oluşturulmasıdır.













SQL Server 2008 ile beraber ortaya çıkan bu hata çeşidi, sizlere SQL Server Management Studio nun bir hediyesidir. SQL Server Management Studio sizlerin yanlışlıkla bir tabloda kritik bir değişilik yapmamanız için bu sistemi oluşturmuştur. Ancak bu engel özellikle tasarım aşamasında tabloların çok sık değiştiği zamanlarda, aşırı can sıkıcı olabilmektedir. Dolayısı ile bu engelden kurtulmak özellikle veritabanı tasarlarken sizi çok rahatlatacaktır.
Çözüm yolu ise gene SQL Server Management Studio(SSMS) dan geçer. Başlangıç olarak Tools menüsü altından Options seçeneğini seçiniz. (SSMS – Tools – Options)

Açılan pencere de sol menüden Designer bölümünü seçtikten sonra , sağ tarafa açılan panel de bulunan Prevent saving changes that require table re-creationalanındaki kutudaki seçimi kaldırısanız SSMS az önceki hatayı bir daha göstermeyecektir.

21 Haziran 2011 Salı

Veritabanı indeksleme nasıl çalışır?


Neden ihtiyaç duyulur?
Veriler disk tabanlı belleklere depolandığında, bloklar halinde depolanır. Bu bloklara bütünlük içinde erişilmesi, onları atomik disk erişim operasyonları yapar. Disk blokları genelde bağlı listeler gibi yapılandırılmıştır; her ikisi de verinin tutulduğu kısım ve bir sonraki düğüme gösteren pointer kısmından oluşur ve her ikiside ardarda depolanmak zorunda değildir.
Sıralama yapılmamış bir alanda arama yapmak Lineer Arama yapmayı gerektirir, bu da N/2 blok erişimi gerektirir. Buradaki N tablonun disk üzerinde bulunduğu blok sayısıdır. Eğer bu alan key yani anahtar olmayan bir alan ise arama N tane blok erişimi gerektirir.
Halbuki sıralanmış bir alan olsaydı Binary Arama kullanılabilir, bu da log2 N blok erişimi gerektirir. Bununla birlikte key olmayan alan sıralanmış ise tablonun geri kalanı duplicate değerleri bulmak için aranmaz. Çünkü alan sıralanmış olduğu için aranandan değişik bir değere erişildiğinde arama bitmiş demektir. Böylece performans önemli ölçüde artar.
İndeksleme nedir?
İndeksleme belirli sayıdaki kaydın birden fazla alanda sıralanması demektir. Bir tablodaki bir alanda indeks oluşturunca, alanın değerini ve bu değerin ilişkili olduğu kaydı işaret eden bir pointer tutan diğer bir veri yapısı oluşturur. Daha sonra bu indeks yapısı üzerinde Binary Arama yapılabilmesi için sıralanır.
İndekslemenin dezavantajı disk üzerinde ekstradan alana ihtiyaç duymasıdır.
Nasıl Çalışır?
Öncelikle örnek bir veritabanı tablo şemasının ana hatlarını çizelim;
Alan adı           Veri tipi      Disk üzerinde kapladığı alan
id (Primary key)   Unsigned INT   4 byte
firstName          Char(50)       50 byte
lastName           Char(50)       50 byte
emailAddress       Char(100)      100 byte
Not: varchar yerine char kullanılmasının sebebi değerin disk üzerinde kapladığı alanın kesin boyutu belirlemek için kullanılmıştır. Bu örnek veritabanı 5 milyon row a sahiptir ve indexlenmemiştir. Değişik sorguların performansı analiz edilecektir.Bunlar id(sıralanmış anahtar alanı) ve firstName(sıralanmamış anahtar olmayan alan) dir.
Örnek 1
Örnek olarak verilen veritabanı r = 5,000,000 kayıtlı, R = 204 byte sabit boyutta kayıt uzunluğu ve blok boyutu B = 1024 byte tır. Tablonun bloklama faktörü bfr = (B/R) = 1024/204 = 5 her bir disk bloğundaki kayıt sayısı. Tabloyu tutmak için gerekli toplam blok sayısı N = (r/bfr) = 5000000/5 = 1,000,000 blok.
id alanındaki arama ortalama N/2 = 500,000 blok erişimi gerektirir, id alanının aranan değerde olup olmadığını kontrol etmek için. Ama id alanı sıralı olduğu için Binary Arama yapılarak ortalama log2 1000000 = 19.93 = 20 blok erişimi ile bulunabilir. Gördüğünüz gibi bu müthiş bir gelişmedir.
Şimdi firstName alanı ne sıralanmıştır, ki böyle olduğu için Binary Arama yapamayız, ne de değerler unique dir, bu yüzden de tablo sonuna kadar aranmalıdır yani N = 1,000,000 blok erişimi gerektirir. İşte burada indekleme yapmak çok faydalıdır.


Söylendiği gibi index kaydı sadece indexlenen alanı ve orijinal kayda işaret eden pointer ı barındırmaktadır. firstName alanı için index şeması aşağıdaki gibidir:
Alan adı            Veri tipi      Disk üzerinde kapladığı alan
firstName           Char(50)       50 byte
(record pointer)    Special        4 byte

Örnek 2
Örnek olarak verilen veritabanı r = 5,000,000 kayıtlı ve index kaydı uzunluğu R = 54 byte ve varsayılan blok büyüklüğü B = 1,024 byte tır. İndeksin bloklama faktörü bfr = 1024/54 = 18 herbir disk bloğu için kayıt sayısı. Tabloyu tutmak için gerekli blok sayısı N = (r/bfr) = 5000000/18 = 277,778 bloktur.
Şimdi firstName kullanarak yapılan arama indeks yapısından faydalanarak performansı arttırır. Yani bu indeksin Binary Aramasının ortalama blok erişimi log2 277778 = 18.08 = 19 dir.
Ne zaman kullanılmalı?
Görüldüğü gibi indeks oluşturmak fazladan disk alanı gerektirir. İndeksleme yapısı sadece aramalarda işe yarar. Yeni kayıt güncelleme ve silme işlemlerinde ekstra işlem zamanı ve disk alanı gerektirir. Bu yüzden sadece aramaları hızlandırmak için yapılmalı ve yüksek veri bulunan tablolarda gerekli alanlar için yapılmalıdır.

17 Haziran 2011 Cuma

C# Static Constructor

C# ta static constructor için performans değerlendirmesi: Microsoft ve birçok kod geliştirici static constructorların ciddi bir yük getirdiği konusunda uyarıyorlar. Static constructorlara aynı zamanda type initializer de denir, çünkü bunlar tiplere referans verirler, instancelara değil. Aşağıda C# dilinde static constructorlar için yapılan test bulunmaktadır. Hangisinin yararlı olduğuna karar verebilirsiniz.


Örnek

Aşağıda static contructoru bulunan ve bulunmayan olarak iki sınıf bulunmaktadır. Kullandığınız çoğu sınıfın static constructoru yoktur. Sonuca göre static constructorlar tipe her ulaştığınızda ciddi bir yavaşlamaya sebep oluyor.

Static Constructor a sahip bir class [C#]

/// /// Bu tip static constructora sahiptir.
/// 
static class HasStaticConstructor
{
    ///     /// Public field
    ///     public static int _test;

    ///     /// Static constructor public alanı initialize eder
    ///     static HasStaticConstructor()
    {
 _test = 1;
    }
}

Static Constructoru olmayan bir class [C#]

/// /// Bu tip static constructora sahip değildir.
/// 
static class NoStaticConstructor
{
    ///     /// Public field initialize edilir
    /// 
    public static int _test = 1;
}

Benchmark (Karşılaştırmalı Test) notları

Döngü: 1000000000
Detaylar:    _text alanı her döngüde erişilir.

Static constructor performans testi

Sınıf 1: Static constructoru olan
Zaman:    3208 ms

Sınıf 2: Static constructoru olmayan
Zaman:     319 ms

Özet

Static constructor kullanmak uygun olabilir, ama çok yavaşlar.Runtime bunları inline atamaları optimize edebildiği yolla optimize edecek kadar akıllı değil. Bazen lazy loading kullanmak uygun olabilir. ( Lazy Loading: bir değişkenin her erişildiğinde null kontrolü yapılıp eğer null ise initialize etmek).

13 Haziran 2011 Pazartesi

ASP.NET MVC nedir, ne işe yarar, niçin ve ne zaman tercih edilmelidir?

ASP.NET MVC’yi anlamak için “WebForms”un ne olduğunu bilmek ve anlamış olmak gerekir. Bundan dolayı öncelikle biraz webformsa değinmek istiyorum.
Klasik ASP ile web geliştirenlerin .NET’e geçişi ile birlikte hayatlarına giren ilk şey “WebForms” olmuştur. Asp.Net programlamada başlangıç seviyesinde, mantığı tam olarak anlaşılamasa da, giriş seviyesi bir programcı dahi webformsu aktif olarak kullanır. Basit bir şekilde anlatmak gerekirse; bir aspx sayfasında bulunan asp.net server kontrollerine (textbox, dropdown, vb.) girilen verilerin programatik olarak işlenmesi için koda gönderilmesini sağlayan sayfa yapısına webforms diyebiliriz. Bu işlemi gerçekleştirmek için bize yardımcı olan mekanizmalar vardır. Postback ve Viewstate bunların başında gelir. Postback bu kontrollerdeki veriyi koda gönderme eylemine verilen isimdir. Viewstate ise postback öncesinde bu formlara girilmiş olan verilerin postback sonrasında tekrar kullanılabilir olmasını sağlayan mekanizmadır. Örneğin aşağıdaki gibi basit bir aspx sayfamız olsun.

Bu sayfadaki textbox’a bir yazı girip, checkbox’a tick atıp, butona tıklandığında textboxa girilen yazıyı sayfanın başına yazdırdığımızı düşünelim. Bunun için Visual Studio’da designerdaki butona çift tıklarız ve bizi code behind’a yönlendirir ve bu buton için bir event oluşturur. Bu eventin içine Response.Write(TextBox1.Text) benzeri bir kod yazarız. Daha sonra bu sayfayı çalıştırıp, butona tıkladığımızda sayfa bir kere refresh yapar (kendini tazeler) ve tekrar aynı sayfayı açar.

Textboxa girdiğimiz yazı, olması gerektiği gibi sayfanın başında gözükür. Ayrıca textbox’ın içinde yazı hala duruyordur ve checkbox da ticklenmiş durumdadır. Oysa sayfa kendini refresh etmiştir. Refresh eyleminin aynı sayfayı tekrar açtığını düşünürsek (adres çubuğundaki url değişmez), o sayfaya ilk defa girildiğinde olduğu gibi boş bir şekilde açılması beklenir. Bunu test etmek için sayfa boş iken textboxa bir yazı girin checkbox’a tick atın ve daha sonra browser’ınızın refresh butonuna basın. Bunu yaptığınızda göreceğiniz üzere textbox’taki yazı kaybolur ve checkbox boşalır. Sayfa ilk açıldığı şekline geri döner. Fakat butona tıklayıp sayfayı refresh ettirdiğinizde her şey yerinde duruyordur. İşte buradaki butona tıklama eylemi sonucu sayfanın refresh yapmasına postback denir. Bu refresh sonunda textbox’a girdiğimiz yazının durması ve checkbox’ın tickli kalmasını da viewstate mekanizması sağlar. Postback ile textbox’taki yazı koda gönderilir. Kod bu yazıyı alır, işler, sayfanın başına yazar ve tüm bunlar refresh anında olur. Refresh tamamlandığında her şey istediğimiz gibidir. İşte tüm bu olaylar zincirinin ve mekanizmaların tamamına “WebForms” denir.
Basit anlamda webformsun işleyiş şekli ve yapısı böyledir. Fakat Asp.Net MVC’de yapı bu şekilde değildir. MVC’de postback, viewstate, codebehind, server kontrolleri (textbox, checkbox) ve bu kontollerin eventleri yoktur. “Olamaz! Bunlar olmadan sayfa nasıl çalışır!” dediğinizi duyar gibiyim. Evet alışık olduğumuz bu yapı Asp.Net MVC’de farklı bir şekildedir. Peki neden farklı? Bu yapı gayet güzel çalışıyor. Bunu neden farklı bir yapıda kullanma ihtiyacı duyuyum ki? Benzeri soruların cevabı ise; webformsun bu yapısının bazı dezavantajları olduğu ve bu dezavantajların mvc’de olmamasıdır. Bazı web projelerinde webformsun birazdan bahsedeceğim dezavantajları tahammül edilemeyecek derecelere ulaştığı için Asp.Net MVC, WebForms’a alternatif olarak geliştirilmiştir. Fakat bu MVC’nin daha iyi, webformsun daha kötü olduğu veya mvc’nin webformsun yerine geçeceği gibi bir anlam taşımamaktadır. Projenin türüne göre tercih edilebilecek birer alternatiftirler.
Şimdi gelelim webformsun dezavantajlarına. Öncelikle bu dezavantajlardan bahsedeceğim. Daha sonra mvc’nin bunları nasıl çözdüğünü elimden geldiğince anlatmaya çalışacağım. Bu çözümleri incelerken mvc’yi de anlamaya çalışmış olacağız.
1.) Viewstate, sayfadaki server kontrollerinin durumunu hafızasında tutmak için client tarafında gizlenmiş bir hidden input oluşturur. Bu input webforms ile geliştirilmiş her aspx sayfasında vardır. Web browser’ınızda herhangi bir aspx sayfasının kaynağına baktığınızda “__VIEWSTATE” isimli bu inputu görebilirsiniz.

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLT
c1MDU0Nzg2MWQYAQUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja0tleV9fFgEFCUNoZWNrQm94
MX5gT8EYawMsUp79Tkt2Gz2HkU/i" />


Gerçek hayat uygulamalarında bu inputun value’su o kadar büyür ki boyutu yüzlerce kilobyte’ı bulur. Bu da client tarafında gereksiz bir yavaşlığa neden olur. Server tarafında ise bu viewstate değerini oluşturmak ekstra iş yükü demektir. Hele bir de günde milyonlarca kez ziyaret edilen bir web projesi ise, bu yavaşlık ve iş yükü tahammül edilemez olur. Yukarıda bahsettiğim gibi Asp.Net MVC’de viewstate yoktur. Bundan dolayı mvc’de böyle bir yavaşlık söz konusu değildir. Peki mvc’de viewstate yoksa sayfadaki kontollerinin durumunu nasıl hafızada tutacağız? Merak etmeyin Asp.Net MVC’de bu işi gören bir mekanizma var ve bu mekanizma ne client’a ne de server’a ekstra iş yükü getiriyor. Bu işi http’nin yapısına uygun bir şekilde çok daha doğal yollar ile gerçekleştiriyor.
2.) Webforms’da sayfa yaşam döngüsü (page life cycle) vardır. Yukarıdaki örnekte kısaca bahsettiğim üzere sayfanın çalışma anında bir tür olaylar zinciri gerçekleşir. Butona tıklandığında o butonun click eventi tetiklenir, daha sonra postback başlar, veriler koda gider, kod veriyi işler ve tekrar sayfaya gönderir. Basit bir uygulamada kısa ve hızlı bir döngüdür bu. Fakat kompleks uygulamalarda maalesef bu kadar hızlı olmamaktadır. Hele bir de o sayfada onlarca server kontrolü bir aradaysa çok daha uzun sürer. Eventler havada uçuşur. Önce hangisi tetiklendi? Sonra hangisi tetiklenecek? Şimdi ne olacak? Aynı anda birden fazla eventi nasıl tetiklerim? Bir sürü karmaşa ortaya çıkar. Codebehind event metotlarıyla dolar. Hangi event hangi kontrolündü karıştırırsınız. Designera geri dönüp o kontrole çift tıklayıp codebehind’taki onun eventine gitmek gibi bir zahmete katlanırsınız. İnanın bana büyük web uygulamalarında bu sizi çığırından çıkarır. Asp.Net MVC’de bu eventlerle boğuşmak zorunda değilsinizdir. MVC sizi Page_Load eventindeki “Page.IsPostBack değilse” kontrolünü yapma derdinden de kurtarır.
3.) Webforms’da asp.net server kontolleri otomatik olarak html elementlerine dönüştürülür. Siz o kontrolün html’ine müdahale edemezsiniz. Yaptığımızın işin web sitesi geliştirmek olduğunu düşünürsek web’in temeli olan html’de tam kontrol sahibi olamamamız hoş bir durum değildir. Özellikle standartlara uyumlu sayfa tasarlama gibi bir kaygımız varsa (ki olmalıdır) server kontolleri size bu esnekliği sağlamamaktadır. Server kontrollerinin css’lerinde de tam kontrol sahibi değilizdir. Ayrıca server kontolleri bazen gereksiz html kodları da üretebilmektedir. MVC’de server kontrolleri olmadığı için standart html elementlerini kullanırız. Bu da size sayfanızın html’inde tam kontrol verir.
4.) Büyük web projelerinde N-Layer, N-Tier, vb. metodolojileri kullanarak programınızın mantık (logic) kısmı ile tasarım (presentation) kısmını birbirinden ayırırsınız. Böylece projenin yazılımsal olarak yönetimi daha kolay olur. Webformsdaki codebehind yapısı aslında bu metodolojilere ters düşmektedir. Çünkü presentation layer’ınızda yoğun olarak kod yazarsınız. Bir çok mantıksal işlemi aspx sayfasına bağlı codebehind’da gerçekleştirirsiniz. MVC’de tasarım ile mantık çok iyi bir şekilde ayrılmıştır. Tasarımı bir kere bitirdiğinizde tekrar tekrar oraya geri dönmek zorunda kalmazsınız. Artık işiniz daha çok mantıksal işlemlerdir, bu katmana yoğunlaşırsınız.
Temel olarak bu dört dezavantajın yanında diğer bazı dezavantajlar da mevcuttur. Fakat konuyu uzatmamak için onlara bu yazıda değinmeyeceğim. Yukarıdaki dezavantajlar ele alındığında büyük bir web projesi için Asp.Net MVC’nin tercih edilmesi akıllı bir yol olarak gözüküyor değil mi? Peki mvc sadece bu dezavantajları gideren bir yapı mı? Kesinlikle hayır. Asp.Net MVC’nin bize kazandırdığı daha birçok yeni ve kullanışlı özellik de mevcut. Bunlardan en önemlisinin “Routing” mekanizması olduğunu söyleyebilirim. Routing, bir aspx sayfasına URL üzerinden gelen çağrıları anlamlı hale getirdikten sonra işlenmesi için mantıksal yapının olduğun koda (logic) yönlendirme işini gerçekleştiren mekanizmadır. Örneğin “www.abc.com/kategori/altkategori/sayfa” şeklinde bir url olduğunu düşünelim. Bu url’i web browserda adres çubuğuna girip enter’a basıldığı an asp.net mvc’de ilk olarak routing mekanizması çalışır. Routing bu url’deki ana domainden (www.abc.com) sonra gelen “/” ile ayrılmış kısımları (kategori, altkategori, sayfa) parçalar, daha sonra mantıksal kodun (logic) içerisinde bunlara uygun olan metotları bulup oraya yönlendirir. Logic’de gerekli işlemler yapıldıktan (veritabanından verilerin çekilmesi, işlenmesi, vb.) sonra tekrar Routing devreye girer ve işlenmiş bu verilerin gösterileceği uygun aspx sayfasını bulup oraya yönlendirir. Routing'in sağladığı bu yapı sayesinde url’ler çok daha anlamlı hale gelir. Böyle olunca da arama motorları bu url’leri daha iyi indeksler ve siteniz üst sıralarda çıkar. Webforms’da bu yapıyı oluşturabilmek için ekstra zahmete girersiniz. Webforms’da url rewrite denilen teknik ile bu işlem gerçekleştirebilmektedir fakat mvc’de olduğu kadar hızlı ve doğal değildir.
Routing’i anlatırken aslında Asp.Net MVC’yi anlamaya bir giriş yapmış olduk. Genel itibariyle mvc’nin çalışma mantığı routing’deki bu yapı üzerine kuruludur. URL’den bir istek gelir, o isteğe uygun metot (Controller) bulunur, bu metod aldığı bu isteği yerine getirmek için uygun business logic metotlarını (Model) çalıştırır ve son olarak buradan dönen anlamlı veriler uygun aspx sayfalarına (View) yönlendirilir.
Burada parantez içerisinde belirttiğim “Model”, “View”, “Controller”lar da bir araya gelip MVC’yi oluşturur.

Bu yazıda Asp.Net MVC’ye detaylı sayılabilecek bir giriş yapmış olduk. Planım bunu bir yazı dizisine çevirip MVC’nin tamamını detaylı bir şekilde incelemek ve sizlerle birlikte örnek bir uygulama geliştirmek. Umarım bu planımı gerçekleştirebilirim. Bir sonraki yazıda Model-View-Controller yapısının nasıl çalıştığına göz atıp, örnek bir asp.net mvc projesi oluşturarak bunu pekiştiririz. Şimdilik bu kadar. Diğer yazıda görüşmek üzere.