Archive for the Yazılım Category

Kodsal yolla windowsun sistem renklerini değiştirebilmek için user32.dll API’si ve ona ait SetSysColors fonksiyonu kullanılmaktadır. Windowsdaki mevcut tanımlanmış renklerin kodlarını da aynı API’den GetSysColor ile alabiliriz. Bu fonksiyonları projelerimizde kullanabilmek için aşağıdaki gibi tanımlıyoruz.C# için;

[DllImport("user32.dll")]
static extern bool SetSysColors(int cElements, int[] lpaElements, int[] lpaRgbValues);

[DllImport("user32.dll")]
static extern uint GetSysColor(int nIndex);
 

VB.NET içinse;

Declare Function SetSysColors Lib “user32″ (ByVal nChanges As Integer, ByRef lpSysColor As Integer, ByRef lpColorValues As Integer) As Long

Declare Function GetSysColor Lib “user32″ (ByVal nIndex As Long) As Long  

Set işlemi yapılırken verilen parametreler sıra ile değiştirilmek istenen renk sayısı, değiştirilecek olan renk dizisi, ve bu renklerin yeni değerleridir.  Renk bilgisini ise sabit tanımlanmış değişkenlerden verebilmekteyiz.  Ve bunlar sıra ile şunlardır:

COLOR_SCROLLBAR – 0 : Scrollbar rengi

COLOR_BACKGROUND – 1 : Masaüstü rengi

COLOR_DESKTOP – 1 :  Masaüstü rengi

COLOR_ACTIVECAPTION – 2 : Aktif pencere başlığında sol taraftaki renk (gradient aktif ise) 

COLOR_INACTIVECAPTION – 3 : Pasif pencere(ler)in başlığında sol taraftaki renk (gradient aktif ise) 

COLOR_MENU – 4 : Menü arkaplan rengi

COLOR_WINDOW – 5 : Pencere arkaplan rengi

COLOR_WINDOWFRAME – 6 : Pencere çerçevesinin rengi

COLOR_MENUTEXT – 7 : Menülerdeki yazı rengi

COLOR_WINDOWTEXT – 8 : Penceredeki yazı rengi

COLOR_CAPTIONTEXT – 9 : Pencere başlık yazısının rengi

COLOR_ACTIVEBORDER – 10 : Aktif pencerenin çerçeve rengi

COLOR_INACTIVEBORDER – 11 : Pasit pencere(ler)in çerçeve rengi

COLOR_APPWORKSPACE – 12 : MDI uygulamaların arkaplan rengi

COLOR_HIGHLIGHT – 13 : Seçili alan  (SelectedItem) arkaplan rengi

COLOR_HIGHLIGHTTEXT – 14 : Seçili alan yazısının rengi

COLOR_BTNFACE – 15 : 3D nesnelerin görünen yüzünün ve dialag boxların arkaplan rengi

COLOR_3DFACE –15 :  3D nesnelerin görünen yüzünün ve dialag boxların arkaplan rengi

COLOR_BTNSHADOW – 16 : 3D nesneler için gölge rengi

COLOR_3DSHADOW – 16 : 3D nesneler için gölge rengi

COLOR_GRAYTEXT – 17 : Gri (disable edilmiş) yazı rengi

COLOR_BTNTEXT – 18 : Buton üzerindeki yazıların rengi

COLOR_INACTIVECAPTIONTEXT – 19 : Pasif başlıklardaki yazının rengi

COLOR_BTNHIGHLIGHT – 20 : Butonun 3D isaretlenmesi rengi

COLOR_3DHIGHLIGHT – 20 : 3D nesneler için seçim rengi

COLOR_3DHILIGHT – 20 : 3D nesneler için seçim rengi

COLOR_3DDKSHADOW – 21 : 3D nesneler için koyu gölge rengi

COLOR_3DLIGHT – 22 : 3D nesneler için açık gölge rengi

COLOR_INFOTEXT – 23 : Tooltiplerin yazı rengi

COLOR_INFOBK – 24 : Tooltiplerin arka plan rengi

COLOR_HOTLIGHT – 26 : Tıklanmış hyperlinklerin rengi

COLOR_GRADIENTACTIVECAPTION – 27 : Aktif pencere başlığında sol taraftaki renk (gradient aktif ise). Gradient özellikleri için SPI_GETGRADIENTCAPTIONS fonksiyonu kullanılabilir.  

COLOR_GRADIENTINACTIVECAPTION – 28 : Pasif pencere(ler)in sağ taraftaki renk (gradient aktif ise)

COLOR_MENUHILIGHT – 29 : Flat menüde seçili alan rengi (Windows 2000’de desteklenmemektedir.) 

COLOR_MENUBAR – 30 : Flat menü çubuğunun arka plan rengi (Windows 2000’de destekelenmemektedir.) 

Kod içerisinden yukarıdaki sabitlerden yararlanılarak mevcut renk değerleri okunanabilir (get) ve ya değiştirilebilir (set). Örneğin grafik uygulamalarımızda windows renkleriyle ile çizim-yazı vs yapmamız gerekebilir. Bu tip durumlarda GetSysColor ile istediğimiz renk bilgisini elde ebiliriz. Mesela masaüstü rengini şöyle alabiliriz: 

uint a = GetSysColor(1); //uint a = GetSysColor(COLOR_DESKTOP);

İlave olarak .NET ortamından windows renklerine ulaşmak için SystemColors sınıfından da yararlanabiliriz. Ancak bu sınıftan sadece okuma yapabildiğimiz için bu renkleri değiştirmek istersek SetSysColors fonksiyonunu kullanmamız gerekecektir. (Yapılan değişiklik windows genelinde etkili olacaktır.) Örneğin seçili alan (selecteditem) rengini şöyle değiştirebiliriz:  

SetSysColors(1, COLOR_HIGHLIGHT, RGB(0, 100, 0)); //SetSysColors(1,13,RGB(0,100,0)); 

RGB kodları içinde RGB-Hexadecimal renk tablosuna bakılabilir. 

.NET ortamından windows bileşenlerine ulaşmak ve windowsun hali hazırda yaptığı işlemlere ulaşmak, kullandığı fonksiyonları bizim de kullanabilmemiz için windows API lerden yararlanırız. Bu anlamda kullanacağımız API listesine Platform Invoke (P/Invoke) sitesinden ulaşabiliriz.

Görev çubuğundaki (taskbar)  uygulamalara ulaşabilmek için de user32.dll API’sinden yararlanıyoruz.  C# uygulamarında API tanımlarını DllImport attribute’u ile yapıyoruz:

[DllImport("user32.dll")]
private static extern int GetWindowText(int hWnd, StringBuilder title, int size);

Burada user32.dll API’si içinde yeralan GetWindowText fonksiyonunu projemizde kullanacağımızı bildiriyoruz. 

Örnek uygulamamızda yer alan EnumWindows fonksiyonu ile windowsta açık olan pencerelerin listesini elde ediyoruz.  EnumWindowsProc ile de bu ekranlarda tek tek dolaşarak başlığını GetWindowText fonksiyonu ile alıyoruz. Ve bu değerleri bir listboxa yazdırıyoruz.

Örnek Uygulamayı İndir

Yazılım devi Microsoft, veritabanı yönetim sistemi olan SQL Server’ın en yeni versiyonu olan SQL Server 2008′e özel bir isim atadı ve çıkış zamanını açıkladı.  SQL Server 2008′in çıkış zamanı olarak 2008′in ikinci çeyreği gösterildi. Resmi olarak kullanılma zamanı ise 27 Şubat 2008. Denver’da gerçekleştirilen Worldwide Partner Conference’da, beklenen zamandan ileride bir tarihin açıklanmasının nedeni olarak; bazı stratejik değişiklikler öne sürüldü. Bunun yanı sıra, SQL Server 2008, “Katmai” özel ismiyle bilinecek. 

Kaynak: http://shiftdelete.net

Windows projelerini oluştururken genellikle bir MDI form (parent) ve onun içinde açılan çocuk (child) formlar şeklinde yapmaya çalışırız. Bu makalede bu şekilde bir uygulamada inheritance ve singleton patternin nasıl uygulanacağını göreceğiz.
Öncelikle yapmaya çalıştığımız projedeki ana formda (MDI) solda bir ağaç (tree), üstte bir menü ve altta da durum çubuğu (statusbar) olsun. Ağaç yapımızda şöyle olsun:
anamenu.jpg

Buradaki her alt düğüm (node) bir ekranı (formu) temsil etmektedir ve bu küçük uygulamamızda 6 child fom bulunmaktadır. Tabi ki bu tip projelerde child form sayısı çok daha fazla olmaktadır. Ayrıca bu child formlar birbirlerine benzediklerinden (örneğin her child formda üstte menu olması, altta statusbar olması, ekranı kaplamış bir groupbox olması, zemin renginin yeşil olması gibi bir takım ayarlar…) her formu tek tek projemize ekleyip bu ayarları hepsinde tek tek yapmak hem zaman kaybı olacaktır hem de ileride bakımını ve yönetimini zorlaştıracaktır. Bu sebeple projemizde interitance kullanacağız. Inheritance temel olarak bir sınıfın özelliklerini kalıtsal olarak başka bir sınıfa aktarmaktan ibarettir. (Detaylı bilgi için bakınız.) Bunun için bir tane temel form yaratıp, bu forma her ekranda olmasını istediğimiz özellikleri vereceğiz ve diğer tüm formları bu temel formdan inherit edeceğiz. Bunun için projemize yeni bir form ekliyoruz istediğimiz özellikleri veriyoruz.frmbase.jpg

Yeni yaratacağımız formları ise Project > Add New Item > Inherited Form şeklinde oluşturacağız. Standart form eklemeden farklı olarak eklediğimiz formun hangi formdan türediğini soracak ve listeden temel formumuzu seçeceğiz. Peki ya formlarınız daha önceden eklenmişse ve siz sonradan bu şekilde bir yapıya geçiyorsanız ne olacak? O zaman da formunuzu tanımladığınız yerin hemen altında inherit kodunu yazmanız yeterli olacaktır:

Public Class FrmKategoriTanim  Inherits FrmBase

Buraya kadar yaptığımız girişten sonra asıl makale konumuza geçelim. Ana ekranda gördüğümüz gibi her alt nodeda child formumuzu çağırıyoruz

Dim frm As New FrmUrunTanim 

frm.MdiParent = Me

frm.Show()

Örneğin ürün tanım ekranı açıkken, tekrar aynı ekranı açmak istediğimizde yeni bir ürün tanım ekranı açılacaktır. Bu şekilde her tıklamada yeni bir ekran açılacaktır, ancak biz istiyoruz ki child form hiç açılmamışsa bir kez açılsın, eğer açıksa bize açık ekranı getirsin. Bunu aslında mdi formun ActiveMdiChild propertysi (çağrıldığı andaki açık olan child formları verir) içinde basit bir for..next döngüsü kurup açmak istediğimiz form zaten açık mı değil mi diye bakarak anlayabiliriz. Ancak biz burada farklı bir yöntem uygulayacağız ve singleton design pattern ile inheritance karışımı bir çözüm üreteceğiz. Singleton’da genel prensip bir instance’nın (burada, “New FrmUrunTanim”)  daha önceden oluşturulup oluşturulmaıdığını tespit etmek, instance yoksa yenisini yaratmak varsa, eskisini döndürmek şeklindedir. Temel formumuz olan FrmBase üzerinde yaptığımız işlemlerin diğer tüm formları da etkilediğini söyledik. Bu anlamda örneğin her formun load eventi altında standart bir işlem yapıyorsak bunu sadece FrmBase formunun load eventina yazmamız yeterli olacaktır. Bu sebeple bizde singleton ile ilgili kodlarımızı her forma yazmaktansa FrmBase altına yazacağız: 

Private _FormLoaded As Boolean

Private _instance As Form

Public Function GetInstance(ByVal willLoadedForm As Type) As Form   

 If _FormLoaded = False Then     

   _instance = CType(Activator.CreateInstance(willLoadedForm), Form)       

   AddHandler Me._instance.Closed, AddressOf Me.WhenFormClosed       

   _FormLoaded = True   

 End If

 _instance.Focus()

Return _instance

End Function

Private Sub WhenFormClosed(ByVal sender As Object, ByVal e As EventArgs)    

 Dim closingForm As Form = CType(sender, Form) 

 RemoveHandler closingForm.Closed, AddressOf Me.WhenFormClosed     _FormLoaded = False

End Sub

Ana formda ise kodlarımızı şu şekilde düzenliyoruz:

Private Sub mainTree_DoubleClick(ByVal sender As Object,ByVal e As EventArgs)

    Dim nd As TreeNode = Me.mainTree.SelectedNode

    If ((Not nd Is Nothing) AndAlso (nd.Nodes.Count = 0)) Then

      Dim frm As Form = Nothing  

      Select Case nd.Name      

       Case “kisi”     

        frm = FrmKisiTanim.GetInstance(GetType(FrmKisiTanim))    

       Case “kategori”      

        frm = FrmKategoriTanim.GetInstance(GetType(FrmKategoriTanim))

       Case “urun”

         frm = FrmUrunTanim.GetInstance(GetType(FrmUrunTanim))

       Case “satis”

         frm = FrmUrunSatis.GetInstance(GetType(FrmUrunSatis))

       Case “stok”

         frm = FrmStokDurumu.GetInstance(GetType(FrmStokDurumu))

       Case “satis_raporu”

         frm = FrmSatisRaporu.GetInstance(GetType(FrmSatisRaporu))  

    End Select 

    If (Not frm Is Nothing) Then  

      frm.MdiParent = Me

      frm.Show()

    End If 

 End If

End Sub

FrmBase altında yazdığımız kodlarda _FormLoaded ile formumuzun yüklenip yüklenmediği bilgisini, _instance ile de yüklenen form bilgisini tutuyoruz. Formlarımızın yeni bir instancenı almak için Activator sınıfından yararlandık. CreateInstance metodu ile Type cinsinden verilen bir nesnenin instance alınabilmektedir. Burada tüm formlarımızın ilave constructorı olmadığını varsaydık. Eğer parametre ile formlarımızı açmamız gerekiyorsa CreateInstace metoduna ikinci parametre olarak bu constructor parametrelerini array olarak geçebiliyoruz. Formumuzun kapatıldığını anlamak için de _instance’ın FormClosed eventini yakalayıp _FormLoaded = false yapmamız gerekmektedir. (Bu kodu doğrudan FrmBase’in FormClosed eventine yazamıyoruz, çünkü aynı formu tekrar açmak istediğimizde dispose edilmiş bir forma ulaşmaya çalıştığımıza dair bir hata alırız.)  Formlarımızı ana formdan çağırırken FrmBase yerine ilgili formdan çağırdık, sanki kodları oraya yazmışız gibi :)  

Örnek Uygulamayı İndir

Bütün veritabanı işlemlerinde bir connection tanımlar ve bunun vasıtasıyla veritabanımıza bağlanıp istediğimiz işlemleri yaparız. Farklı her connection tanımladığımızda bu connectionlar connection pool’da saklanır. Eğer tekrar aynı connectiona ihtiyaç duyarsak tekrar tanımlama yaparız, ama artık bu yeni bir connection olmayıp pool’dan bize atanır. Böylelikle aynı veritabanına defalarca bağlanırken (üstelik kullanıcı sayısının arttığını da düşünürsek) daha kısa sürede bağlantı yapmamızı sağlayacaktır. Bu da daha fazla performans demektir.

Şimdi bu connection pooling ile karşılaşabileceğimiz bir sorunun senaryosunu hazırlayalım. Öncelikle aşağıdaki örnek kodumuzu ele alalım:

SqlConnection con = new SqlConnection

(server=.SQLEXPRESS;database=TEST;UId=User1;Pwd=123;”);

SqlCommand cmd = new SqlCommand

(“SELECT Count(*) FROM TARIH”, con);

con.Open();

int i = Convert.ToInt32(cmd.ExecuteScalar());

con.Close();

//Bir takım işlemler….

SqlConnection con2 = new SqlConnection

(server=.SQLEXPRESS;database=master;UId=sa;Pwd=123;

Pooling=False);

SqlCommand cmd2 = new SqlCommand

(“ALTER DATABASE TEST SET READ_ONLY”, con2);

try

{

  con2.Open();

  cmd2.ExecuteNonQuery();

}     

catch (SqlException ex)

{

   Console.WriteLine(ex.Message);

}

finally

{

con2.Close();

}

Burada yapılanı incelersek TEST veritabanına User1 kullanıcısı ile bağlanıp bir sorgu çalıştırılıyor. Burada ne yapıldığı önemli değil, sonuçta veritabanına bağlanıp bir işlem yapıldığını görmek yeterli. Senaryomuz gereği bu veritabanı üzerinde bir işlem yapmamız gereksin. Bu herhangi bir işlem olabilir, basit olması açısında veritabanını READ_ONLY yapmaya çalışacağız. (Önemli olan alter database edebilmek) Buraya kadar bir sorun yokken çalışma zamanında aşağıdaki hata ile karşılaşıyoruz.

Timeout expiredThe timeout period elapsed prior to completion of the operation or the server is not responding. ALTER DATABASE statement failed.

Peki, bu da nereden çıktı şimdi? Evet, connection poolingden… Öncelikle ilk connectionı yarattığımızda bu connection poola atıldı. Daha sonra sa ile sisteme bağlanıp TEST veritabanı üzerinde alter database yapmak istediğimizde ise bize yukarıdaki hatayı verdi. SQLexpress management studioyu açıp sp_who ile bağlı kullanıcılara bakalım.

 connection1.jpg

Sonuçlara baktığımızda User1 kullanıcısının bağlı olduğunu ama “uyuduğunu” görüyoruz. Bu da bizim daha sonra sa ile bu veritabanı üzerinde işlem yapmamızı engelliyor. (SQL 2000 kullanıyorsanız kod tarafında “database currently in use” mesajını alırsınız.)

Gelelim çözümümüze. En basiti, ilk bağlantımızı tanımlarken Pooling=False özelliğini eklemek olabilir. Ancak bu durumda connection poolingin bize sağladığı nimetlerden faydalanamayacağız ki bu istediğimiz bir çözüm değil. Bu durumda 2. bağlantımızı çalıştırmadan hemen önce

SqlConnection.ClearPool(con);

komutunu işletebiliriz. Böylelikle bu connectionı pool’dan temizlemiş oluruz. Buradaki senaryomuzda aynı scope içinde işlem yaptık. Scope dışında isek aynı connectionı pooldan alıp temizleyebilmek için tekrar tanımlamamız gerekiyor. Yani:

SqlConnection con = new SqlConnection

(server=.SQLEXPRESS;database=TEST;UId=User1;Pwd=123;”);

SqlConnection.ClearPool(con);

Hemen burada farklı bir sorunun senaryosunu çizmek istiyorum. Peki, pool bu şekilde değil de farklı bir biçim de temizlenirse ne olur? Mesela sql serverda sorun oldu ve restart oldu, ya da sql admin gitti bizim bu User1 bağlantımızı bize haber vermeden KILL etti. (Yukarıdaki sp_who tablosuna göre KILL 53 komutu ile bağlı kullanıcı düşürülebilir.) Bu durumda poolda engel olacak kullanıcı olmadığından bizim ALTER DATABASE işlemi başarıyla çalışacaktır. Ancak, oldu ya daha sonra yine bizim bu veritabanı üzerinde işlem yapmamız gerekti: 

SqlConnection con4 = new SqlConnection

(server=.SQLEXPRESS;database=TEST; UId=User1; Pwd=123;”);

SqlCommand cmd4 = new SqlCommand

(“SELECT Count(*) FROM TARIH”, con4);

  try

  {

      con4.Open();

      int i2 = Convert.ToInt32(cmd4.ExecuteScalar());

  }

  catch (SqlException ex)

      {

        Console.WriteLine(ex.Message);

      }

  finally

  {

      con4.Close();

  }

Bu seferde farklı bir hata ile karşılaşıyoruz:

A transport-level error has occurred when sending the request to the server. (provider: Shared Memory Provider, error: 0 – Borunun diğer ucunda işlem yok.)

Anlaşılacağı üzere “borunun diğer ucu” gitmiş.Yani, ADO.NET bunun daha önce poolda olduğunu zannediyor ve connectionı bu şekilde tanımlıyor ve işlem yapmaya çalışıyor; ancak başarılı olamıyor. Peki, bu durumda ne olacak? Bu durumda yapılacak şey yine exceptiona düştüğünde poolu temizlemek:

catch (SqlException ex)

  {

      if (ex.Number == 233)

      {

         SqlConnection.ClearAllPools();

      }

  }

Bu durumda, eğer, bu sorgu çok kritik bir sorgu ise tekrar çalıştırılması gerekecektir.

 

Projelerimizde en çok kullandığımız değişken tipi string olsa gerek. String tipinin reference type ve immutuable olması, projelerde hayli yer alması bizim string değişkenlerle yaptığımız işlemlerde performansa ne kadar dikkat etmemiz gerektiğini gösteriyor.  String immutuable bir değişken tipidir, dedik. Bunun anlamı string bir değişkene verdiğimiz değeri (aslında değerin adresini) asla değiştiremeyiz. Bunu basit bir örnekle açıklamaya çalışalım.            

string test = “Veri”;

//Bir takım işler

test = “Data”;

Burada yaptığımız heap’de bir yer ayırıp içine “veri”yi koymaktan ve bu yerin adresini test değişkenine vermekten başka bir şey değil. Daha sonra yapılan ise heap’de bir yer daha ayırıp içine “data”yı koymak ve test değişkenine “data”nın adresini vermek. Yani heap’de aslında iki tane yerimiz var (biri “veri”yi içeriyor diğeri “data”yi) ama test değişkenimiz sadece “data”nın bulunduğu adresi tutuyor. Bu şekilde düşündüğümüzde string üzerinde yaptığımız her yeni atamada aslında içindeki veriyi değil, adresini değiştirmiş oluyoruz ve hafızada (heap’de) belki de farkında olmadan fazladan yer tutuyoruz; ta ki garbage collector (GC) zamanı gelip de “veri” nin adresini tutan herhangi bir değişken bulamayıp temizlediği zamana kadar…  Şimdi de bir karşılaştırma örneğine bakalım. 

string test1 = “veri”;

string test2 = “data”; 

 // Bir takım işlemler 

if (test1.ToUpper() == test2.ToUpper())  

 {      // Bir takım işlemler   }

    Proje çıktısının ilgili yerini ILDASM ile inceleyelim:    

string3.jpg


Görüyoruz ki hafızada test1.ToUpper()’ın sonucu başka bir yerde, test2.ToUpper()’ın sonucu başka bir yerde tanımlanıp farklı değişkenlere alınıyor. (Heap’de “veri”, “data”, “VERİ”, “DATA”  yerleri mevcut ve stackda “VERİ”’nin ve “DATA”nın adresini tutan iki ayrı değişken tanımlanmış) Daha sonra da boolean bir değişken tanımlanıp string fonksiyonlarından Equality kullanılarak karşılaştırıldığını görüyoruz. Peki if bloğunu şu şekilde değiştirirsek ne olur acaba, bakalım:  

if (string.Compare(test1,test2,true) == 0)

   {      // Bir takım işlemler   }

  ILDASM ile proje çıktısının ilgili satırına bakarsak:   

string2.jpg

Fazladan hafızada yer ayırmalar ve değişken tanımlamalar olmamış. Bu da kodumuzun öncekine göre daha performanslı olmasına ve daha az hafıza kullanılmasına sebep olmuştur. String işlemlerinde sıkça kullandığımız bir başka işlem de birleştirmelerdir. Basit bir örnekle bunu da analiz etmeye çalışalım.  

string test = “veri1″;

//Bir takım işlemler 

test += ” veri2″;  

//Bir takım işlemler 

test += ” veri3″;

     

string3.jpg

ILDASM çıktısına ve önceki bilgilerimize göre ilk string birleştirmede aslında heapde bir yer ayrılıp içine “veri1 veri2” yazıldığını ve bunun adresini bizim değişkenimizin tuttuğunu görürüz. Benzer şekilde ikinci birleştirme de heap’de “veri1 veri2 veri3” yazan bir yer ayrıldığını ve bunun adresini değişkenimizin tuttuğunu rahatlıkla söyleyebiliriz. (Heap görüntüsü şöyledir: “veri”, veri1 veri2, “veri1 veri2 veri3” Yani hafızada 3 ayrı yer ayrılmıştır.)  Yani string değişkenimizin içeriğini aslında değiştiremiyoruz, çünkü kendisi immutuable’dır… Bu duruma alternatif çözüm StringBuilder sınıfı ile gelmektedir:   

StringBuilder sb = new StringBuilder();

sb.Append(“veri1″);           

 //Bir takım işlemler 

sb.Append(“veri2″); 

//Bir takım işlemler  sb.Append(“veri3″);

     

Aslında her zaman StringBuilder sınıfını kullanmak istenen performansı vermeyecektir. Bu sebeple String birleştirme işlemi belirli bir sayıda ise + veya concat metodunu kullanmak daha faydalı iken, belirsiz ve fazla sayıda string birleştirmeler de StringBuilder sınıfını kullanmak daha iyi olacaktır. Bu tavsiyeyi MSDN’de de görüyoruz:

“The String class is preferable for a concatenation operation if a fixed number of String objects are concatenated. In that case, the individual concatenation operations might even be combined into a single operation by the compiler. A StringBuilder object is preferable for a concatenation operation if an arbitrary number of strings are concatenated; for example, if a loop concatenates a random number of strings of user input.” 

Projelerimizin minimum kaynak tüketimi ile maksimum performansta çalışmalarını isteriz. Burada da buna nasıl katkı sağlayacağımızı birkaç string işlemi üzerinde incelemeye çalıştık. Belki onlarca satırdan kazanacağımız birkaç ms ve hafızadan tasarruf edebileceğimiz birkaç byte çok fazla bir fark ettirmeyecektir. Ancak unutulmamalıdır ki projelerdeki satır sayısı arttıkça ve yaptığımız işlemler daha da karmaşıklaştıkça bu tip küçük şeylerin aslında ne denli önemli olduğu ortaya çıkacaktır. Ayrıca .NET Framework mimarisinin nasıl çalıştığını anlamamıza bir o kadar da yardımcı olacaktır.  

Çoğu zaman veritabani bağlantılarında connection string özelliğini dinamik olarak oluşturmamız gerekmektedir. Bunun için de string birleştirmeler kullanırız. Benzer şekilde de bir connection stringden bazen server, userId gibi bilgileri parçalayarak elde ederiz. Ancak hepimizin bildiği gibi connection stringler yazılırken farklı formatlarda yazılabilirler ve bu da örneğin bağlanılan database bilgisi yerine baska bir bilgi almamıza neden olurlar. İşte tüm bunların önüne geçmek için .NET 2.0 ile gelen bir sınıf var: SqlConnectionStringBuilder 

SqlConnectionStringBuilder ile çok kolay bir şekilde connection stringler oluşturabiliyoruz; mevcut connection stringler üzerinden de işlemler yapabiliyoruz. SqlConnectionStringBuilder’ın iki tane constructorı vardır ve birisi connection string parameteresi alır.   

Başlıca kullanacağımız özellikleri şunlardır: 

ConnectionString = ConnectionString bilgisini tutar.

DataSource = Bağlanılacam olan ana bilgisayar (server) bilgisini tutar.

InitialCatalog = Ana bilgisayardaki bağlanılacak veritabanı bilgisini tutar.

IntegratedSecurity = Windows güvenliğini kullanarak mı yoksa Sql doğrulama ile mi bağlanacağını belirtir. Default değeri False’dur.

UserID = SQL doğrulama ile bağlanılacak kullanıcı adını tutar.

Password = SQL doğrulama ile bağlanılacak kullanıcının şifresini tutar. 

Sınıfın tüm metodları ve özellikleri için bakınız. 

 Basit olarak aşağıdaki gibi Connection Stringi oluşturabiliyoruz.  

SqlConnectionStringBuilder sqlString =

      new SqlConnectionStringBuilder();

sqlString.DataSource = “(local)”;

sqlString.InitialCatalog = “Northwind”;

sqlString.UserID = “sa”;

sqlString.Password = “123″; 

SqlConnection con =

      new SqlConnection(sqlString.ConnectionString);

Benzer şekilde elimizdeki bir connection string üzerinde de işlem yapmamız gerekebilir. Aşağıdaki örnekte sql doğrulama ile bağlantı sağlayabilecek bir connection stringin windows doğrulama sağlayacak hale nasıl getirildiğini görüyoruz.  

string conString = “Sever=(local);User ID=sa;Password=123;Database=Northwind”;

SqlConnectionStringBuilder sqlString =

new SqlConnectionStringBuilder(conString);

sqlString.Remove(“User ID”);

sqlString.Remove(“Password”);

sqlString.IntegratedSecurity = true; 

SqlConnection con =

    new SqlConnection(sqlString.ConnectionString);

VB.NET 2.0 ile gelen My Namespace bize birçok işi kolay yoldan yapmamızı sağlıyor. Aşağıdaki şekilde My Namespace içindeki sınıfları görüyoruz. Her bir sınıfla bilgisayarımız, uygulamamız hakkında çeşitli bilgiler alıyor ve bir takım işleri çok kolay bir şekilde yapıyoruz. Detaylı bilgi için bakınız.


Ancak Visual Basic’e ait bu namespace C# ortamında doğrudan yer almamaktadır. Tabi bu da C#’da kullanamayacağımız anlamına gelmiyor. Bunun için öncelikle yeni bir C# projesi açıyoruz ve Microsoft.VisualBasic.dll dosyasını referans olarak ekliyoruz: 

Hangi sınıfları projemizde kullanacağımız bulmak için object browserda VisualBasic.DLL assembly’sini inceliyoruz.

Böylelikle projemize ekleyebileceğimiz sınıfları buluyoruz: (İhtiyacınız olmayanı eklemeyebilirsiniz.)

using Microsoft.VisualBasic.ApplicationServices; using Microsoft.VisualBasic.Devices;

Sonrada istediğimiz sınıftan bir instance türeterek istediğimiz işlemleri yapabiliyoruz: 

Bad Behavior has blocked 31 access attempts in the last 7 days.