30 Temmuz 2011 Cumartesi

Tek Satırda If Komutu

If-Else yapılarının tek satırda toplanmış hali;


   sonuc = (sayi%2==1) ? "Tek":"Çift";
   
Yapısı kısaca,  

(koşul ifadesi) ? "True" : "False";

20 Temmuz 2011 Çarşamba

C# Dosya Yazma-Okuma İşlemleri(Input-Output)

C#'da uygulama geliştirirken çokça kez bir dosyaya veri yazma, veya bir dosyadan veri okuma gibi ihtiyaçları hissederiz. Şimdi size, basit olarak en kısa yoldan, bir dosyadan veri okunmasını ve yazılmasını anlatacağım.

Öncelikle dosyadan veri okuma ve yazma işlemlerimizi yerine getiren 2 sınıfımız var. Veri okuma işlemleri için, StreamReader,veri yazma işlemleri için de StreamWriter classlarını kullanırız. Kısaca kodlar üzerinden anlamaya çalışalım.

1-Veri Okuma :


FileStream file = new FileStream(@"C:\\ergin2.txt", FileMode.Open, FileAccess.Read);
StreamReader read = new StreamReader(file);


FileStream classının constructorında, sınıfa parametre olarak sırasıyla, dosyanın yolu,dosya belirtilen yolda bulduktan sonra hangi işlemi yapacak (burada açmasını istedik),üçüncü parametre olarak da bu dosyanın okunacağını belirtiyoruz. Ardından, verileri okumamızı sağlayan StreamReader sınıfına bu dosyamızı veriyoruz.


string s = "";
string line = "";

while ((line = read.ReadLine()) != null)
{
       s += line + ",";
}
if (s.Length > 1)
s = s.Substring(0, s.Length - 1);


Ardından, senaryomuza göre dosyada satır satır bulunan id'leri ReadLine() metodu sayesinde okuyup, son satır gelene kadar aralarına virgül koyarak ayırıyoruz. En son satırda da virgül olacağından, o virgülü silmek için de substring metodunu kullanıyoruz. Böylece, örnek dosyamızda;

123
456
789
...
şeklinde olan veri;

123,456,789

şeklinde okunacak.

2- Veri Yazma :



StreamWriter sw = new StreamWriter(@"C:\\ergin2.txt", true);

sw.WriteLine(txtId.Text);


Burada da, yine aynı şekilde, önce StreamWriter nesnemizi oluşturduk. Yalnız, burada dikkat etmemiz gereken nokta, StreamWriter'in string ve bool parametresini alan overload'ını kullanmamız gerekir. Aksi taktirde, veri okurkenki gibi 3 parametreli overload'ını kullanırsak, dosyamıza append edemeyiz verilerimizi. Yani verilerimiz sürekli üst üste yazılacağından, biri silinirken diğeri yazılacak, dolayısıyla sadece en son veri ekranda yazılmış olacak. Bu yöntemle, ikinci parametreye true vererek, append işlemi yapmak istediğimizi söylüyoruz ve TextBox'ımızın içinde yazan değeri de yazmış oluyoruz belirttiğimiz dosyaya.

Görüldüğü gibi, veri okuma ve veri yazma işlemleri oldukça kolay. Yapmamız gereken, FileStream nesnesini oluşturup, veri yazılacak veya okunacak dosyayı tanıtıp, hangi işlemleri yapmak istediğimizi belirtip, bizden istenen işleme göre (okuma-yazma) StreamReader veya StreamWriter classlarını kullanıp, gerekli metotlar sayesinde istediğimiz işlemleri yapmak olacaktır.

16 Temmuz 2011 Cumartesi

Asp.Net'de Sayfa İçi Tema Değiştirme

Sitemizde, sayfanın görselliğini kullanıcıya bırakmak için,  tema değişikliği vs. gibi işlemler, son derece profesyonel ve göze hoş gelir. Şimdi, asp.net sayfalarında tema değişikliği nasıl yapılır bunu kısaca anlatmaya çalışacağım.

Öcelikle projemize sağ tıklayıp, add asp.net folder ve Theme diyip temamızı oluşturuyoruz. Temamızın içine css dosyası da ekledikten sonra basit olarak css'in içine arka plan rengi ve yazı rengi verelim. Örneğin bir mavi, bir de kırmızı temamız olsun. Bunun için şöyle bir css kodu yazalım,

Kırmızı Tema

body
{
    background-color:Red;
    color:White;
}

Mavi Tema

body
{
    background-color:Blue;
    color:White;
}

Şimdi de bu tema değişikliğini kullanıcıya bırakalım. Yani kullanıcı isterse Mavi, isterse kırmızı temayı kendi seçip kullansın. Bunun için bir dropdownlist koyup, kullanıcının seçimine göre değişikliği yapalım.

Öncelikle ilk akla gelen, dropdownlist'in autopostback özelliğini true yapıp, selectedindexchanged eventi tetiklendiğinde tema değişikliğini yapmak. Fakat bu işlemi yaptığımızda göreceğiz ki, uygulama şöyle bir exception fırlatacak;

The 'Theme' property can only be set in or before the 'Page_PreInit' event.

Bunun anlamı, LifeCycle süreci bazı sırayla gerçekleşir. Sayfa oluşurken, 

  • Constructor
  • PreInit
  • Init
  • Load
  • PreRender
  • UnLoad
metotları sırasıyla çalışır ve sayfa oluşur. Dolayısıyla, tema atama, setleme işlemleri de PreInit'de gerçekleştiğinden burada da PreInit metodumuzu yazıp, Temayı setleyelim.

    protected void Page_PreInit(object sender, EventArgs e)
    {
        Theme = DropDownList1.SelectedValue;
    }


Bu kodu yazdığımızda da şöyle bir sorun çıkar. Asp.Net kontrolleri Load eventinden önce oluşur fakat markuptaki halleriyle oluşur. Yani boş bir şekilde sadece DropDownList'in oluştuğunu görürüz. Load metodunda içi dolar. Dolayısıyla PreInit, Load'dan önce çalıştığından hata verecektir. Peki Load eventinden önce kontrollerin değerlerine nasıl erişiriz.

Cevap, Request nesnesi sayesinde. Aslında Load'da da Request ile erişebiliriz fakat, Visual Studio uzun uzun yazmayalım diye, öyle bir kolaylık sağlamış bize DropDownList oluştuğu için. Dolayısıyla PreInit'den seçilen değeri alabilmemiz için şu kodu yazmalıyız;

    protected void Page_PreInit(object sender, EventArgs e)
    {
        if(Request.RequestType == "POST")
        {
            Theme = Request.Form["DropDownList1"];
        }       
    }

kodu RequestType'ını kontrol etmemizin amacı, get taleplerinde var olan temayı default olarak vermek. Yani sayfa ilk açıldığında boş bir template ile açılsın, daha sonra dropdownlist post edildiğinde içindeki değer PreInit metodunda okunsun ve temamız değişsin. Ekran çıktısına baktığımızda ise şöyle bir sonuç görürüz;



Substition Cache Kavramı

Substition Cache kısaca, sayfanın tümünün cachelenip, sadece bazı bölümünün dinamik olarak değiştiği sayfalarda kullanılır. Örneğin, sayfanız 2-3 ayda bir yenileniyordur fakat, sayfanın en altında merkez bankasından o anki kuru alıyorsunuzdur. Çok ufak bir bölüm için, sürekli tüm sayfayı yeniden oluşturup, html render etmeye gerek yok. Bunun yerine tüm sayfayı cacheleyip, sadece o kısmı hariç tutarsak, daha doğru bir kodlama yapmış oluruz. İşte bu tür cacheleme biçimine de Substititon Caching denir.

Substition caching yapmak için, önce tüm sayfayı output cache'e koymamız gerekir. Bunun için sayfamıza,
 

<%@ OutputCache VaryByParam="none" Duration="300" %>


ekleriz. Böylece, şu anda tüm sayfamızı cachelemiş olduk. Şimdi sayfamızda dinamik gelmesini istediğimiz kısmı oluşturmamız gerekecek. Bunun için ToolBox'da bu işlem için Substition kontrolünün olduğunu görüyoruz. Bu kontrolün görevi, bulunduğu kısıma (bu kısım div, td ..vs gibi bir yer olabilir) dinamiklik getirmek. 

2x2'lik bir table oluşturup, kolonlardan birine label ve Substition kontrolünü atıp, sayfanın PageLoad'ına o label'ın text'ine o anki saati yazdıralım. Tabiki tüm sayfa cacheli olduğundan bir de sayfada herhangi bir yere label koyup, o label'a da o anki saati yazdıralım. Bu işlemleri yapıp çalıştırdığımızda göreceğiz ki, sayfada bulunan label, bir kere o anki saati gösterip, 300 sn boyunca sürekli aynı saati cacheden getirecek. Fakat td'nin içinde bulunan saat, sürekli olarak dinamik olarak saati getirecek.

Sayfanın bu şekilde oluşmasını bekleriz. Akıllara şöyle bir soru gelebilir. Sayfa cache'den geldiğinden, page lifecycle süreci çalışmayacak, dolayısıyla html render edilip bize geri dönmeyecek. Çünkü ilk get talebimizde bu işlemler yapılıp cache'e atılmıştı. Peki, substition kontrolü ile gerçekleştirdiğimiz dinamik yapı da, lifecycle sürecine katılmayıp html olarak bize geri gelmeyecek mi? 

İşte bu sıkıntıdan kurtulmak için, Substition kontrolü bizden bir metot yazmamızı istiyor. Bu metot, cache'den gelen, daha önce render edilmiş html'in içine gömüleceğinden, geriye string döndürmeli. Dolayısıyla biz geriye, html formatında bir yapı döndürmeliyiz. Çünkü lifecycle sürecini hatırlarsak, sayfaya talep yaptığımız zaman, compiler  html oluşturup bize geri gönderiyor ve sayfamız ortaya çıkıyor. Burada da, dinamikliği oluşturduğumuz kısım da html'in içinde yer alması gerektiğinden, bizim bu metotda html formatında bir string geri döndürmemiz gerekir. Ayrıca, şunu da unutmamalıyız ki, sayfa cache'den geleceğinden, sayfa oluşmadan bu metot çalışacak. Dolayısıyla metodumuzu static yapmalıyız. Bu durumda metotumuzu yazarsak, basit olarak;


    protected static string DinamikIcerik()
    {
        return string.Format("<İnput type='text' value='{0}' />", DateTime.Now.ToLongTimeString());
    }

Bu metot ismini de Substition kontrolünün property'lerinde bulunan MethodName özelliğine verirsek, artık sayfamız istediğimiz biçimde, sadece belli bölgesi dinamik olacak şekilde cachelenmiş olarak çalışacak. Ekran çıktılarına bakacak olursak;







NOT: Üstteki Labellarda gösterilen saatler, sayfa içerisinde cache'den getirilen saatlerken, altta bulunan saat ise td'nin içinde bulunan substition kontrolü sayesinde dinamik olarak gelen saattir.
NOT2: Yukarıda, yazdığım metotda bulunan span html kontrolünde, blogger editörü html kodlarını derlediğinden bilerek ve isteyerek büyük i -İ- harfini koydum, blogun derleyememesi için. Heyecan yapmayınız.

Http Requestlerinin Dinlenmesi (Page sınıfından kalıtılmayan sınıflarda)

HTTP requestlerini dinleyebildiğimiz ve onlarla ilgili işlemler yapabildiğimiz bazı metotlar, property'ler, kısaca bazı üyeler vardır. Örnek vermek gerekirse, Server.MapPath ile uygulamanın, bulunduğu serverdaki çalıştığı dosyanın tam yolunu verir. Request.QueryString diyerek, sayfaya querystring ile gelen parametreleri alırız, veya Request.Cookies diyerek, daha önce tanımlanmış cookie değerlerine erişiriz. Bunları herhangi bir sayfada yazarken hiçbir sorun olmayız. Fakat, projenize bir class ekleyip, o class içinde herhangi bir yerde bunları çağırmayı deneyin.

Denediğiniz vakit, göreceksiniz ki, Intellisense yardımcı olmuyor. Ama herhangi bir sayfadan yazdığınızda eriştiğinizi göreceksiniz. Bunun nedeni, bu üyelerin Page sınıfında bulunması. Dolayısıyla sayfalarımız da Page sınıfından kalıtıldığından biz bu üyelere erişebiliyorduk. Sınıfımız Page sınıfından kalıtılmadığı için de dolayısıyla erişemiyoruz. 

İşte bu sorunu ortadan kaldırmak için, Http requestlerine ulaşmamızı sağlayan HttpContext sınıfından Current property'si sayesinde, bize gelen Http Requestlerini dinleyebiliyoruz.

int id = Convert.ToInt32(HttpContext.Current.Request.QueryString["I_ID"]);
string username = HttpContext.Current.Request.Cookies["UserName"].ToString();
XDocument doc = XDocument.Load(HttpContext.Current.Server.MapPath("~\\data.xml"));

7 Temmuz 2011 Perşembe

Sql'de Truncate Table Kavramı

Sql'de bir tablomuzda bazı verileri silmek istediğimizde, Delete komutunu kullanırız. Başka bir alternatif yokturdur. Ama tablodaki tüm kayıtları silmek istersek, hem Delete, hem Truncate komutları sayesinde tüm tabloyu boşaltabiliriz.Yani Truncate komutu da Sql'de tüm tablodaki verileri boşaltmak amacıyla kullanılır.

Peki bu iki komut arasındaki fark nedir?

Kısaca, maddeler halinde yazalım.
  • Öncelikle, Truncate kavramı ile bir şarta bakmaksızın tüm tablomuzu boşaltırız. Delete komutunda Where şartı ile belli şartlara bağlayabiliriz.
  • Bence en önemli farklarından birisidir şimdiki maddemiz, Truncate Table yapınca, o tablodaki identity kolonumuz en baştan başlar. Ama Delete yaparsak, en son kaçıncı id'de kalmışsa, oradan devam eder.
  • Truncate Table, Transaction içerisinde kullanılırsa ve işlemimiz rollback olursa geri alınamazlar. Delete komutunda geri alabiliriz.
  • Truncate Table yaptığımızda, eğer o tablo üzerinde Delete Trigger'i varsa, bu trigger tetiklenmez. Delete komutlarında ise tetiklenir.
İşte Truncate Table ile Delete komutları arasındaki en temel fark bunlardır. Son olarak da syntaxlarını, nasıl yazıldıklarını gösterelim;
  • TRUNCATE TABLE Tablo1
  • DELETE FROM Table1
şart koymak istersek,
  • DELETE FROM Table1 WHERE ID=5

5 Temmuz 2011 Salı

Her Yerde Sql :)





İlişkili Tablolarda Veri Silme (Delete Join)

Şu ana kadar Joinleme işlemlerini ve Update Join işlemini görmüştük. Normal Joinleme işlemlerinde, birbiri ile ilişkili iki tablodan veri çekip, rahatlıkla istenilen raporu dökebiliyorduk. Daha sonra da, yine ilişkili tablolarda, gerekli şartları sağlayan kayıtları toplu halde update(Güncelleme) yapabiliyorduk. Bugün de, yine ilişkili tablolarda, belli şartları sağlayan verileri sileceğiz.

Örnek senaryomuz, AdventureWorks üzerinden AltKategorileri 'G' ile başlayan ürünleri silmek istensin bizden. Gördüğünüz gibi, tek tablo işimizi görmüyor. Product tablosundan kayıt sileceğiz ama, bu tablo üzerinden AltKategori isimlerine erişemiyoruz. İşte burada yapmamız gereken şey, iki tabloyu birleştirip, silme işlemini gerçekleştirmek. Bunun için yazmamız gereken kod şu şekilde olmalıdır;


DELETE FROM Production.Product
FROM Production.Product p INNER JOIN Production.ProductSubcategory ps on p.ProductSubcategoryID = ps.ProductSubcategoryID
WHERE ps.Name like 'G%'




Gördüğünüz gibi, önce hiçbir şart yokmuş gibi DELETE FROM Production.Product diyorum, daha sonra da belirtilen şartı sağlamak için joinleme işlemi yapıyorum. Bunun sonucunda, 6 kayıdın Product tablosundan silindiğini görürüz.

Not: Delete sorgusunu kullanarak, birden fazla tabloda veri silmek mümkün değildir. Bunun için birden fazla delete sorgusu çalıştırılmalıdır.

3 Temmuz 2011 Pazar

Sayfa Üzerinden MasterPage Değişikliği Yapmak

MasterPage kısaca, web uygulamalarında tüm web formların ortak özelliğini tutan ve onları sayfalarda gösteren bir mekanizmadır. İsterse 10 sayfamız olsun, tüm sayfalarda görünmesini istediğimiz bir alan varsa (genellikle header,footer ve sidemenu'ler olur) onları MasterPage ile üretip, tüm sayfalara uygularız. Peki, onlarca sayfadan sadece bir sayfa, bu master page'de belli bir alanı göstermek istetmezse?

Örneğin, MasterPage'imizde footer'ınde yazılan text'i sayfanın birinde değiştirelim. Bunun için yapmamız gereken şey, MasterPage'in code behind kısmında footer alanındaki Label'ın text'ini dışarıya setlemek olmak. Bunun için property yazmamız gerekecek. Yazacağımız property şu şekilde olmalı;


    public string FooterText
    {
        get { return Label1.Text; }
        set { Label1.Text = value; }
    }

Gördüğünüz gibi, Label'ın text'ini set bloğu içinde değiştirebilirtiyoruz. Bulunduğumuz sayfada da, MasterPage'in footer kısmındaki yazıyı şu şekilde değiştiririz;

((Main)Master).FooterText = "Bu MasterPage Kodla Değiştirildi";

Burada bilmemiz gereken, herhangi bir sayfa üzerinde, Master diyerek LifeCycle sırasında üretilen MasterPage'in nesnesine ulaşırız. Buradan da az önce yazdığımız property'i değiştirdiğimiz zaman, artık bu sayfada masterpage'deki Footer kısmındaki text'i değiştirmiş oluruz. Dolayısıyla tüm sayfalarda MasterPage normal gözükürken, bu sayfamızda, Footer'da farklı bir yazı yazmış oldu. Farklı değişiklikler için de yine aynı yöntemle, değiştirmek istediğimiz kısımla ilgili property yazıp, onu dışarıya setlemeliyiz. Daha sonra da hangi sayfa üzerindeki MasterPage'i değiştirmek istersek, o sayfadan, MasterPage içerisine yazdığımız property'i cağırıp, gerekli değişiklikleri yaparız.