.Net FrameWork 2.0 da Nullable Tipler

.Net FrameWork 2.0 da Nullable Tipler

.Net Framework 1.0 ve 1.1 de program geliştirirken özellikle çok fazla zorlandığımız konulardan bir tanesiydi bu nullable tipler, özellikle katmanlı bir mimariye göre programınızı geliştiriyorsanız, oldukça problemliydi bu konu, ama .Net Framework 2.0 ile birlikte bu problemi çözmüşler ve artık bir değişkenin değerini nothing (null) olarak atayabiliyoruz. İlk önce neden zorlanıyorduk, Nullable problem neredeydi onu inceleyelim.

Şöyle düşünün, örneğin bir GUI katmanınız var, ve bu GUI katmanınız kullanıcının girdiği veriyi, diğer katmanalara yolluyor ve en son veri katmanı olan Data katmanına geliyor. Data katmanında GUI den gelen ve gerekli doğrulamaları yapılmış olan veriyi veritabanına yazmanız gerekiyor. Aslında yapmak istediğimiz şey bir kullanıcı kayıt formu ve GUI de üç tane textbox ınız var ve kullanıcının bu textboxlardan bazılarına veri girmesi zorunlu bazılarına değil, örneğin kullanıcıya adını soyadını ve yaşını sorduğumuzu düşünelim, adı ve soyadı zorunlu ancak yaşı zorunlu değil. Siz kullanıcının buradan girdiği değerleri hiç bir işlem yapmadan direk controller katmanına yollamalısınız, controller katmanı bu doğrulama işlemlerini yapmalı (GUI Katmanları tamamen veriden bağımsız çalışmalıdır, GUI katmanı girilen verinin rakammı, metinmi olduğu bilgisi ile ilgilenmemeli sadece kullanıcının girdiği verileri başka bir katmana yollamalı, o katman bu verileri düzenlemeli, nedeni ise GUI katmanınızın tipi değişebilir Asp.Net ken Vb.Net olabilir, eğer GUI nin arkasına bazı kodlar yazarsanız, değiştiği zaman o kodları diğer platform içinde yazmanızın gerektiğidir.)  bundan dolayı kullanıcı verileri girdikten sonra ve örneğin Ekle butonuna bastıktan sonra verileri kontroller katmanına yollamalısınız (burada entity gibi yapılarda kullanılabilir, ancak örneği daha doğru ve sade anlatsın diye verileri direk parametre olarak yollayacağım) GUI miz aşağıdakine benzer bir yapıda olmalı,

Kullanıcı Ekle butonuna bastığında ben Controller katmanını çağıracağım Controller Katmanınında KullaniciEkle isimli bir metot bulunuyor ve bu metot 3 tane parametre alıyor, parAdi, parSoyadi ve parYasi. GUI deki Ekle butonundaki kodumuz şöyle

    Private Sub btnEkle_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEkle.Click

        Dim intControllerLayer As ControllerLayer = New ControllerLayer()

        intControllerLayer.KullaniciEkle(txtAdi.Text, txtSoyadi.Text, txtYasi.Text)

    End Sub

Geldik esas problemli olan yere, gerekli doğrulama işlemlerini yaptınız, metinleri denetlediniz istediğiniz kriterlere uyuyormu diye mesela. Ama yaş için işlem yapmaya geldiniz ve hatırlayınız yaş girilmesi zorunlu olan bir alan değildi. Kullanıcının girmemiş olması olasılığı var. Denetlediniz eğer kullanıcı yaşını girmiş ise problem yok, ancak ya girmemişse ? o zaman ne yapacaksınız ? şöyle düşünelim, bir değişken tanımladınız ve tipi integer, eğer Vb.Net yazıyorsanız default olarak değerine sıfır atayacaktır zaten (garbage değeri kalmasın diye) eğer C# yazıyorsanızda değişkene değer atamadan kullanamayacaksınız atayacağınız değerde malesef nothing yada null olamayacak. Çünkü rakamsal değerler (biraz ileride açıklayacağım neden rakamsal olduğunu) nothing yada null tutamazlar. Alternatif bir çözüm deneyelim, eğer kullanıcı değer atamamışsa 0 (sıfır) atayalım, dolayısıyla veritabanınada 0 olarak yazılacak. Ancak ya muhasebe işi yapacak bir uygulama yazıyorsak, rakamlar çok önemli, belki o girilmeyen değer bir çarpım işleminde kullanılacak ve yanlış sonuç çıkmasını sağlayacak. Peki bu alternatif çözümü biraz daha geliştirelim. Nasıl olsa Data katmanım var, yani verilerin veri tabanına yazılmadan önce, Stored Procedure lere parametre eklendiği zamanda şöyle bir kontrol (fonksiyon) yaparım, rakamsal değerlere bak eğer sıfır ise değerleri DbNull.value ata böylece veritabanına giden veri nothing yada null olarak gidecek ve veritabanınıda null olarak tutulacak. Ancak bu seferde gerçekten sıfır olması gereken bir değeri tutamıyorum. Kısacası gördüğünüz gibi kesin ve standart bir çözümü maalesef yok.

Aslında bir çözümü var, kullandığınız her veritipi için bir class yazıp (structureda olabilir), o classın içindede değer nothing (null) mi diye bir değişken tutup, eğer değeri nothing (null) ise bir boolean değeri true yaparsın ve ilk önce onu denetlersin, değer true ise DbNull.Value ile veri tabanına yazarsın. Ancak maliyeti ve zaman kaybını düşünün. Oldukça fazla, her bir primitive tip için bir class tanımlayacaksınız, içinde o değişkenin boyutu olacak bir de boolean değişken olacak ve bir property bir kaçta fonksiyon olacak. Oldukça yorucu ve maliyetli bir iş.

Peki neydi temel sorun ? neden tutamıyorduk nothing değerleri ?

Aslında temel sorun şuydu, CLR da iki tip değişken tipi bulunur, bunlardan bir tanesi Değer tipleri (Value Type) diğeri ise referans tipleri (Reference Type). Değer tipleri örneğin Integer yada Structure şeklindeki tipler, referans tipleri ise String yada diğer Class tipleridir. Referans tiplerine siz nothing (null) ataması yapabilirsiniz, çünkü referans tipleri direk veri ile çalışmazlar, RAM deki adresleri baz alarak çalışırlar, ancak Değer tipleri direk veri ile birlikte çalışırlar ve mutlaka bir veri tutmaları gereklidir. Bundan dolayı nothing yada null olamazlar. Eğer tanımladıktan sonra değer atamazsanız, içlerinde RAM de tanımlanmadan önceki diğer çöp değerleri kalmasın diye içlerini boşaltırlar. Örneğin yukarıdada belirttiğim gibi, mesela eğer rakamsal bir değişken tanımlarsanız değeri 0 olur yada DateTime tipinde bir veri tanımlarsanız değeri, DateTime.Now() olur. Yani her şartta içlerinde bir değer olmalıdır.

Ancak daha çok uğraşmaya gerek kalmadı, .Net Framework 2.0 ile Nullable Tipler geldi ve kullanımıza sunuldu, nasılmı ? Vb.Net kategorisinde yazdığım Genericler ile,

Artık bir class var ve classın içindeki verinin tipi sizin isteğinize göre verilmiş şekilde. Aslında kullanımı yine biraz zahmetli, ama olmamasından iyi :) örneğimizi şöyle geliştirelim, amacımız kullanıcının yaş bölümüne değer girip girmediğine bakmak, eğer değer girmediyse nothing(null) değer yollaması, eğer değer girdiyse doğum yılının hesaplanması olsun, amacı gayet iyi anlattığını düşünüyorum. nasıl kullanıldığını incelemek için az önce yazdığımız kodları düzenleyelim, aşağıda üç katman mevcut, bu üç katmandaki işleri inceleyiniz.

 

Vb.Net kodları aşağıdaki gibidir

    Private Sub btnEkle_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEkle.Click

 

        Dim insControllerLayer As ControllerLayer = New ControllerLayer()

 

        Dim memYil As System.Nullable(Of Integer) = New System.Nullable(Of Integer)

        memYil = insControllerLayer.KullaniciEkle(txtAdi.Text, txtSoyadi.Text, txtYasi.Text)

 

        If memYil.HasValue Then

            MessageBox.Show("Kullanici " & memYil.ToString() & " yilinda da dogmustur")

        Else

            MessageBox.Show("deger atanmamis")

        End If

    End Sub

End Class

 

Public Class ControllerLayer

    Public Function KullaniciEkle(ByVal parAdi As String, ByVal parSoyadi As String, ByVal parYasi As String) As System.Nullable(Of Integer)

        "metinler ile ilgili gerekli duzenlemeleri yaptik

        Dim memYas As System.Nullable(Of Integer) = New Nullable(Of Integer)

        If parYasi = "" Then

            memYas = Nothing

        Else

            memYas = CInt(parYasi)

        End If

        Dim insBusinessLayer As BusinessLayer = New BusinessLayer

        Return insBusinessLayer.KullaniciEkle(parAdi, parSoyadi, memYas)

    End Function

End Class

 

Public Class BusinessLayer

    Public Function KullaniciEkle(ByVal parAdi As String, ByVal parSoyadi As String, ByVal parYasi As System.Nullable(Of Integer)) As System.Nullable(Of Integer)

 

        If parYasi.HasValue Then

            Return DateTime.Now.AddYears(-1 * parYasi.Value).Year

        Else

            Return Nothing

        End If

    End Function

 

C# kodları ise şöyle

public partial class Form1 : Form

{

       public Form1(){InitializeComponent();}

       private void btnEkle_Click(object sender, EventArgs e)

       {

             ControllerLayer insControllerLayer = new ControllerLayer();

             int? memYil = insControllerLayer.KullaniciEkle(txtAd.Text, txtSoyad.Text, txtYas.Text);

 

             if (memYil.HasValue) {

                    MessageBox.Show("Kullanici " + memYil.ToString() + " yilinda da dogmustur");

             }

             else{

                    MessageBox.Show("deger atanmamis");

             }

 

       }

}

public class ControllerLayer {

       public ControllerLayer(){}

       public int? KullaniciEkle(string parAdi, string parSoyadi, string parYasi) {

             int? memYas;

             if (parYasi == "")

             {

                    memYas = null;

             }

             else {

                    memYas = int.Parse(parYasi);

             }

             BusinessLayer insBusinessLayer = new BusinessLayer();

             return insBusinessLayer.KullaniciEkle(parAdi, parSoyadi, memYas);

       }

}

public class BusinessLayer {

       public BusinessLayer(){}

       public int? KullaniciEkle(string parAdi, string parSoyadi, int? parYasi){

             if (parYasi.HasValue){

                    return DateTime.Now.AddYears(-1 * parYasi.Value).Year;

             }

             else{

                    return null;

             }

       }

}

Gördüğünüz gibi kullanması hiçte zor değil, özelliklede c# daki tanımlaması çok kolay, Vb.Nette System.Nullable classının generic olarak kullanıp, bir tip veriyorsunuz, C# da ise veri tipinin sonuna bir “?” ekliyorsunuz. HasValue property i ile içinde bir değişken varmı yoksa değeri null mi diye bakıyorsunuz ve değeri Value property i ile okuyorsunuz.

Makale ile ilgili, öneri, istek ve eleştirileriniz için aşağıdaki mailimi kullanabilirsiniz

Döküman Arama

Başlık :

Kapat