2.1. INTRO 2.2. CLASS OBJECT MENTALİTY – SINIF VE NESNE 2.2.1. CLASS - SINIF 2.2.2. OBJECT – NESNE 2.2.3. FİELD AND PROPERTY 2.2.4. ENCAPSULATİON
63 64 64 64 64 66
FORM:
67
2.3. METODS İN CLASS 2.4. CONSTRUCTOR – YAPICI METOT 2.5. THİS KEYWORD 2.6. ACCESS MODİFİERS (ERİŞİM BELİRTEÇLERİ) 2.7. STATİC CLASS VE STATİC MEMBERS 2.8. REFERANCE TYPE VE VALUE TYPE 2.8.1. VALUE TYPE (DEĞER TİPİ) 2.8.2. REFERENCE TYPE (REFERANS TİPİ) 2.9. INHERİTANCE 2.9.1. BİRDEN FAZLA CLASSDAN MİRAS ALMAMIZ GEREKTİĞİNDE NE YAPMAMIZ GEREKİR? 2.10. ABSTRACT CLASS
3.1. MS SQL KAVRAMLARI & TERİMLERİ 3.1.1. VERİ TABANI (DATABASE) NEDİR ? 3.1.2. MS-SQL SERVER NEDİR ? 3.1.3. SERVER TYPE 3.1.4. SERVER NAME 3.1.5. AUTHENTICATION 3.1.5.1. Sql Server Authentication 3.1.5.2. Windows Authentication 3.1.6. LOGIN 3.1.7. PASSWORD 3.2. MS SQL TANITIM 3.2.1. OBJECT EXPLORER 3.2.2. NEW DATABASE 3.2.3. DATABASE İÇERİSİNDEKİ YAPILAR 3.2.4. SQL’DE Kİ DATA TYPE’LAR 3.3. NORMALİZASYON 3.4. VERİTABANI TAŞIMA VE YEDEKLEME İŞLEMLERİ 3.4.1. BACK-UP RESTORE YÖNTEMİ 3.4.2. ATTACH – DETECH YÖNTEMİ 3.4.3. GENERATE SCRIPTS 3.5. TRANSACT SQL 3.5.1. DATA DEFİNİTİON LANGUAGE – DDL 3.5.2. SYSTEM DATABASES 3.5.3. NORTHWİND SCRİPT 3.5.4. DATA MANUPULATİON LANGUAGE – DML 3.5.4.1. SELECT SORGULARI 3.5.4.2. Kolonlara İsim Vermek 3.5.4.3. SELECT SORGULARI (Where – And, Or, Between, In, Not In) 3.5.4.4. WHERE Sorgusu 3.5.4.5. BETWEEN Kullanımı 3.5.4.6. IN 3.5.4.7. LIKE 3.5.4.8. ORDER BY 3.5.4.9. ZAMAN METOTLARI 3.5.4.10. AGGREGATE FUNCTION – Bütünleşik Sorgular 3.5.4.11. SUB QUERY – ALT SORGULAR 3.5.4.12. TOP ve DISTINCT 3.5.4.13. GROUP BY
JOIN (BİRLEŞTİRME) HAVING Zaman Metotları INSERT COMMAND IDENTITY ve SCOPE IDENTITY UPDATE (GÜNCELLE) DELETE DECLARE – DEĞİŞKENLER VIEWS – SANAL TABLOLAR WITH ENCRPYTION VIEW ile INSERT – Sanal Tabloları Kullanarak Insert İşlemi FQN – Fully Qualified Name STORED PROCEDURE – SAKLI YORDAM IF ELSE – Karar Yapıları DÖNGÜLER FUNCTION YAPISI TRIGGER - TETİKLEYİCİ TRANSACTION SQL’de PERFORMANS INDEX YAPISI Görev Tanımlama Kullanıcı Oluşturma ve Rol Belirleme
12.1. ASP.NET SAYFA YAŞAM DÖNGÜSÜ: 12.2. ASP.NET WEB FORMLAR 12.2.1. FORM ELEMENTİ VE ÖZNİTELİKLERİ 12.3. POSTBACK KAVRAMI 12.4. ASP.NET SUNUCU KONTROLLERİ 12.4.1. VİEWSTATE 12.4.2. HTML KONTROLLERİ 12.5. VALIDATION KONTROLLER 12.6. DATA KONTROLLER 12.6.1. REPEATER 12.6.2. GRIDVIEW
281 283 284 284 286 287 287 288 295 295 297
9|Sayfa
12.6.3. DATALIST 12.6.4. DETAILS VIEW 12.6.5. ASP.NET WEB USER CONTROL 12.7. MASTER PAGE 12.8. STATE MANAGAMENT(DURUM YÖNETİMİ) 12.9. CACHİNG (ÖNBELLEKLEME) 12.9.1. DATA CACHİNG (VERİ ÖNBELLEKLEME) 12.9.2. OUTPUT CACHİNG (ÇIKTI ÖNBELLEKLEME) 12.10. MEMBERSHİP 12.10.1. LOGIN VIEW
303 307 308 311 314 325 326 327 328 336
13. ASP.NET AJAX
337
13.1. 13.2. 13.3. 13.4.
337 338 339 340
ACCORDİON MENU TAB CONTROL ASP.NET AJAX İLE VERİLERİ ÇEKMEK LOADİNG İŞLEMİ
15.1. MVC NEDİR ? 15.2. MODEL VİEW CONTROLER 15.2.1. MODEL 15.2.2. VİEW 15.2.3. CONTROLLER 15.3. ASP.NET MVC ÇALIŞMA MANTIĞI 15.4. ASP.NET MVC AVANTAJLARI DEZAVANTAJLARI 15.4.1. NEDEN ASP.NET WEB FORMS ? 15.4.1.1. ViewState Kullanımı 15.4.1.2. Zengin Sunucu Kontrolleri 15.4.1.3. Olay Güdümlü Programlama (Event Driven Programming) 15.4.2. NEDEN ASP.NET MVC ? 15.4.2.1. Performans 15.4.2.2. Yeniden Kullanılabilirlik (Reuseability) 15.4.2.3. Test Driven Development 15.4.2.4. Yazılım Geliştirme Süresi 15.4.2.5. Kontrollerin Yönetimi için istemci Taraflı Geliştirme (Client-Side Development) 15.5. ASP.NET MVC PROJESİ OLUŞTURMA 15.5.1. ŞABLON TÜRLERİ 15.5.2. FRAMEWORK VERSİYONU
ÖNSÖZ Merhaba sevgili BilgeAdam öğrencileri. Sizler için oluşturmuş olduğumuz bu kaynak kitap, Bilge Adam Akademi’de almış olduğunuz Yazılım Uzmanlığı (.NET) eğitiminin konularını içeren ve çalışmalarınızda size destek olacak tüm konu anlatımı ve örnekleri içermektedir. Amacımız sizler eğitim görürken ders anlatımları ile paralel olarak gidecek, konu tekrarlarını herhangi bir dış kaynağa ihtiyaç duymaksızın gerçekleştirebileceğiniz yanı sıra ders müfredatı dışındaki ekstra yararlı bilgilere erişebileceğiniz bir kaynak oluşturmaktır. Bu kitaptaki tüm bilgiler seçkin eğitmenlerimiz tarafından özenle hazırlanmış, tüm öğrencilerin gelecek hedefleri doğrultusunda kariyer planlarını destekleyecek nitelikte bilgiler içermektedir. Sadece eğitim süresinde değil yazılım hayatınız boyunca size yol gösterebilecek doğrultuda hazırlanmıştır.
12 | S a y f a
YAZARLAR
Ozan OĞUZ Mustafa Emin YALDIZDIR Tuğberk KUYTUL Murat VURANOK Alp KURTBOĞAN
13 | S a y f a
INTRODUCTION 1.1. PROGRAMLAMANIN TARİHÇESİ İlk bilgisayar 1945 yılında Amerika Birleşik Devletlerinin II.Dünya Savaşı sırasında, Amerika ordusunun bilim insanlarından savaş sırasında birtakım hesaplamaları daha hızlı yapabilmek için bir istekte bulunmasıyla üretildi. Ordunun amacı daha hızlı hesaplar yaparak savaştaki stratejisini geliştirmekti.
Bu bilgisayar tam 4 yılda üretildi ve Eniac adını aldı. Eniac 167 m2’lik bir alan kaplıyordu ve tam olarak 30 ton ağırlığındaydı. ENIAC bir sayının görüntüsünü ayırabiliyor, eşitlikleri karşılaştırabiliyor, çarpabiliyor, bölebiliyor, toplayabiliyor, çıkartabiliyor ve kare kökleri hesaplayabiliyordu. ENIAC'ın akümülatörleri (ön kayıt bölgeleri) hem toplama hem de hafıza işlevi görüyordu. ENIAC'a veriler bir IBM kart okuyucusu aracılığı ile veriliyordu. İşlenmiş veriler ise yine bir IBM delikli kart makinesi sayesinde alınıyordu ve bu kartlar yine IBM’in üretmiş olduğu bir delikli kart okuyucu tarafından deşifre ediliyordu.
Eniac’ın arkasından gelen Edvac ve Ordvac gibi bilgisayarlar Kapalı Kart Devre sistemi ile üretilmeye başladı. Kapalı Kart Devre Sistemi dediğimiz yapı akım varsa 1, akım yoksa 0 değerini alarak çeşitli işlemlerin elektronik devre üzerinde gerçekleştirilmesiyle oluşur. Bu işleme Makine Dili denir. Bilgisayarın çalışma mantığıda günümüzde aynıdır.
Makine dilini mantıklı bir şekilde programlamak için yazılım dilleri geliştirilmeye başlamıştır, ilk programlama dilleri makine diline çok yakın olduğundan geliştirmek oldukça zordu. Ardından Fortran, Cobol, C dilleri ortaya çıkmaya başladı.
Programlama dillerinin hespisinin kendine özgü özellikleri vardı fakat nesneye dayalı programlama olarak adlandırdığımız OOP mimarisi hiç bir dilde yoktu. Bu sebeple OOP modeli geliştirilerek C diline entegre edildi böylece ortaya C++ dili çıkmış oldu. Ardından OOP dilleri türemeye başladı. C++’ın ardından Java çıkmış ve büyük
14 | S a y f a
ilgi görmüştür. 2000 yılında Microsoft büyük bir adım atarak bir çok programlama tekniğini ve özelliğini kapsayan .Net platformunu çıkartmıştır.
1.2. PROGRAMLAMAYA GİRİŞ 1.2.1. Programcı/Yazılımcı Kimdir ? 1.2.1.1. Yazılım Değişik ve çeşitli görevler yapma amaçlı tasarlanmış elektronik aygıtların birbirleriyle haberleşebilmesini ve uyumunu sağlayarak görevlerini ya da kullanılabilirliklerini geliştirmeye yarayan makine komutlarıdır.(Bilgisayarların, bir işi yapması için tasarlanan komutlar (emirler) zinciri)
1.2.1.2. Yazılımcı Belirli işlevlere sahip programları geliştiren, kullandığı platform ve teknolojiye hakim, insanların hayatlarını kolaylaştıran ve algoritmik düşünce yapısıyla düşünen kişilere yazılımcı denir.
1.2.2. Programlama Terimleri 1.2.2.1. Compiler Yazdığımız kodları derleyerek aradile dönüştüren derleyicidir. İleriki konularda bahsedeceğimiz bir konudur, yazdığımız kodların makine diline dönüştürülmesini sağlar. 1.2.2.2. Compile Yazdığımız kodları derleyiciye göndererek derleme işlemine verilen addır. 1.2.2.3. Object Oriented Programming Nesneye yönelik programlama, günlük hayattan nesneleri bilgisayar ortamına taşımamızı sağlayan bir yöntemdir. 1.2.2.4. Common Language Runtime (CLR) Ortak Dil Çalışma Platformu C# dilinin derleyicisidir. 1.2.2.5. Framework Programlama dillerinin komutlarını tanıyan ve bu kodları işleyen kütüphanedir. .Net Framework 2.0 dan başlamış ve son olarak 4.5 versiyonu kullanılmaktadır. Örneğin Windows işletim sisteminde, Java Runtime Enviroment yüklü olmadığında java dili ile yazılan bir programı çalıştıramayız. Aynı şekilde .Net Framework yüklü olmayan bir bilgisayarda C# kodları çalıştırılamaz. 1.2.2.6. Visual Studio Microsoft tarafından geliştirilen ve bir çok programlama dilini destekleyen bir IDE’dir. 1.2.2.7. Integrated Development Environment (IDE) Yazılım geliştiricilerinin hızlı ve rahat bir şekilde yazılım geliştirebilmesini amaçlayan, geliştirme sürecini organize edebilen birçok araç ile birlikte geliştirme sürecinin verimli
15 | S a y f a
kullanılmasına katkıda bulunan araçların tamamını içinde barındıran bir geliştirme ortamıdır. 1.2.2.8. C Sharp (C#) C++ dili üzerine eklemeler yapılarak, Microsoft tarafından geliştirilen yazılım geliştirme dilidir. C++’ da “++” ifadesi C dili üzerine ‘Nesneye Yönelik Programlama’ eklenmesinden kaynaklanmaktadır. # ifadesi ise C++’da bulunan Nesneye Yönelik Programlamada bulunan eksiklikler ve mantık hatalarının düzenlenmesinden dolayı C++ dilinden sonraki isim C++++ yerine dört adet + karakterlerinin birleşmesiyle # olarak kullanılmıştır. 1.2.2.9. .Net Csharp ile geliştirilen programlarda tüm işlemleri geliştiren kapsamlı bir platformdur. 1.2.2.10. Syntax Sözdizimi anlamına gelmektedir. Bir programlama dilinde ki ifadelerin uyulması gereken kurallar bütünüdür. 1.2.2.11. Intermediate Language (IL) Ortak dil anlamına gelmektedir.
1.2.3. Compiler – Derleyiciler
Bir programlama dilinde yazılmış olan kaynak kodu makine diline çeviren yazılımdır.
1.2.4. Common Language Runtime (CLR)
Ortak dil çalışma platformu, .Net alt yapısında programların çalışmasını denetler ve programın işletim sistemi ile iletişim kurmasından sorumludur. C# program kodu MSIL Assembly’e, Assembly'i de CLR’e çevrilerek çalıştırılabilir bir makina koduna dönüşür. Bu .NET programlarının derlenip çalıştırılma mantığıdır.
CLR kısaca yazılan programın tüm işletim sistemlerinde çalışmasını sağlamakla görevlidir. Örneğin biz java ile yazılmış bir oyunu Windows işletim sistemine sahip bir bilgisayarda oynamak istediğimizde, Java Runtime Environment’ı bilgisayarımıza kurmalıyız.
1.3. VISUAL STUDIO GİRİŞ 1.3.1. Tanışma Microsoft tarafından geliştirilen ve bir çok programlama dilini destekleyen bir IDE’dir. Birçok programlama dilini ve standartları destekler. Eklentileri ile geliştirici araclarını arttırır ve kod yazmayı kolaylaştırarak hızlandırır.
16 | S a y f a
Bizler C Sharp kodlarımızı Visual Studio isimli IDE’de yazacağız. Yavaş yavaş Visual Studio’yu tanımaya başlayabiliriz.
Visual Studio açıldığında karşımıza Start Page ekranı gelecektir. (Resim 1.1) Bu ekran Visual Studio kullanıcıları için bazı bilgilendirmeler ve kısa yollar sağlamak için bulunmaktadır.
Sol tarafta bulunan panelden, proje bilgilerini yönetebiliriz.
New Project : Yeni bir proje oluşturmak için kullanabileceğimiz kısa yoldur. Dilersek; File menüsü altından New > Project yolunu izleyerek proje oluşturabiliriz.
Open Project : Daha önceden oluşturduğumuz bir projeyi açmak için kullanabileceğimiz seçenektir. Projeyi açmak için açılan pencereden proje yolu bulunur ve proje içerisindeki .sln uzantılı dosya seçilerek açılır.
Solution Dosyası (.sln) : Microsoft Visual Studio içersinde program hazırlarken daha düzenli çalışmayı sağlayan metin tabanlı bir dosyadır. ‘.sln’ uzantılı dosyaları çalıştırmak için Visual Studio programına ihtiyaç vardır. Recent: En son kullandığımız projelerin bilgilerini tutar. Recent panelinin amacı, üzerinde çalıştığımız projeyi Microsoft Visual Studio programını çalıştırdığımızda daha kolay bir yöntem ile vakit kaybetmeden çalıştırmaktır. Burda projelere sağ tıklayarak listeden kaldırabilir, sln dosyasının bulunduğu klasörü görme işlemleri gibi özellikleri kullanabiliriz.
17 | S a y f a
Get Started : Resim 1.1’de bulunan Get Started paneli Microsoft Online’da paylaşılan Microsoft Visual Studio’yu tanıtmaya yönelik videoları içeren bir paneldir. Yöntem 1: File > New > Project yolunu takip ederek yeni bir proje oluşturma penceresini oluşturabiliriz.
Yöntem 2: Start Page sayfasında bulunan New Project bağlantısına tıklayarak yeni proje oluşturma penceresine ulaşabilirsiniz.
1.3.2. Yeni Bir Proje Oluşturmak
Açılan pencereyi kullanarak yeni bir proje oluşturabiliriz.
Açılan pencerede sol tarafta bulunan Templates seçeneği altından, Visual C# seçeneği seçilir.
Visual
C#
altında bulunan kategorilerden hangi platform için çalışacağımızı seçmeliyiz.
Windows : Windows sekmesi C# dili ile Desktop (Masaüstü) uygulamaları geliştirmek için kullanılan yapıları tutar. Web : Web tabanlı uygulamalar için kullanabileceğimiz yapıları tutar. Office : C Sharp kodlarımızı, Microsoft Office programları ile kullanabileceğimiz yapıları içerir. Cloud : Microsoft Azure platformu üzerinde çalışacağımız zaman kullanacağımız yapıyı barındırır. Silverlight : Silverlight uygulamaları geliştirirken kullanacağımız yapıları içerir.
18 | S a y f a
WCF : Servis odaklı mimariye dayalı yapıları içerir. Projelerimizde servis çalıştırmak istediğimizde gerekli yapıları WCF sekmesi altından oluşturabiliriz.
Açılan pencerede bulunan alandan projemizin .net Framework versiyonunu seçmemiz gerekmektedir. Framework versiyonları arasında ki farkdan ilerleyen konularda bahsedeceğiz.
Kullanacağımız template’i seçtikten sonra istediğimiz item’ı belirlememiz gerekiyor. Biz ilk olarak “Windows Form Application” nesnesini seçiyoruz.
.Net Framework versiyonunu seçtikten sonra hemen yanında bulunan Sort By seçeneği ile aşağıda bulunan platformları isimlerine göre sıralayabilirsiniz.
Projemiz ile ilgili isim, kayıt yeri ve solution bilgilerini belirleyebiliyoruz.
Name : Oluşturduğumuz projemizin ismidir. Location : Oluşturulan proje dosyası hangi dizine kayıt edilecek bilgisidir. Solution : İçerisinde birden fazla proje barındıran yapıdır. Burada Solution ismini belirtiyoruz
19 | S a y f a
Create Directory for solution : Proje oluşturulurken proje dosyasının (.sln uzantılı) projenin dosyaları ile aynı klasörde olmasını isterseniz bu seçenek işaretlememelisiniz.
1.3.3. Visual Studio Panelleri Yeni bir proje oluşturduktan sonra karşımıza visual studio panelleri gelecektir. Bu panelleri kullanarak projemizi şekillendirebilir ve kolaylıkla yönetebiliriz. Şu anda kullanacağımız paneller
Solution Explorer Properties Window Toolbox
Solution Explorer Paneli ile visual studio programını tanımaya başlayalım.
Solution Explorer Oluşturduğumuz projenin dosyalarını yönetmek için kullandığımız paneldir. Solution Explorer panelini kullanarak projemize yeni yapılar, klasörler ve dosyalar ekleyebilir ve bu dosyaları yönetebiliriz.
Toolbox C Sharp’da kullanabileceğimiz kontrollerin bulunduğu araç kutusudur. Projemiz içerisinde kullanmak istediğimiz kontrolleri sürükle bırak yöntemiyle veya toolbox penceresinde kontrolün üzerine çift tıklama ile projemize eklenebilir. Projelerimizde kullanacağımız kontrollerin tamamı bu pencerede ki kontrollerden oluşturmaktır.
Properties Window Kullandığımız kontrollerin ve formun özelliklerini değiştirebildiğimiz paneldir. Varsayılan değerleri barındırır. Kontrollerimize ait tüm özellikleri bu panelden değiştirebiliriz. Kolay kullanım açısından alınabilecek sabit değerleri de listeler.
1.3.4. Programlamaya Başlarken : Bilgiler ve Kısa Yollar App.config : Configuration dosyasıdır. Projemiz ile ilgili ayarların bulunduğu dosyadır. İleriki konularda Application Configuration dosyasının detaylarını inceleyeceğiz. References : Kütüphane dosyalarının bulunduğu paneldir. Code Behind : C Sharp kodlarımızı yazabildiğimiz ekrandır.
20 | S a y f a
F4 : Properties penceresini açar. F5 : Hazırladığımız projeyi derler ve çalıştırır. F6 : Hazırladığımız projeyi derler. F7 : Hazırladığımız form’da Code Behind ekranına geçiş yapar. CTRL + Shift + B : Hazırladığımız projeyi derler. Designer.cs Dosyası : Projemizde kullandığımız kontrollerin boyutlarını, renklerini ve benzeri bilgilerini tutan dosyadır.
1.4. YAZILIMCI DOSTU BİLGİLER 1.4.1. C#’da Yorum Satırı C Sharp’da kodlarımıza açıklama satırları ve notlar bırakmak isteyebiliriz. Bu notlar ileriye dönük geliştirmeye kolaylık sağlar. Csharp’ta yorum satırları aşağıdaki gibi kullanılır. C Sharp’da yorum satırları koyu yeşil renktedir.
1.Yöntem //Tekli yorum satırıdır. Tek satırda yorum yazmak istediğimizde kullanabiliriz.
2.Yöntem /* * Birden fazla satırda yorum yazmak : Satır 1 * Birden fazla satırda yorum yazmak : Satır 2 * Birden fazla satırda yorum yazmak : Satır 3 */
1.4.2. Word Wrap Visual C Sharp’da uzun kod satırları, yatay olarak sayfayı uzatır. Biz satır sonuna geldiğimizde kodlarımızın alt satırdan devam etmesini isteyebiliriz. Bu özelliği açmak için aşağıdaki yolu takip edebilirsiniz.
Tools > Options > Text Editor > All Languages Yolu altında bulunan Word Wrap Seçeneği işaretlenir. 21 | S a y f a
1.4.3. Line Numbers Visual C Sharp’da kod satırlarının satır numaralarını görmek isteyebiliriz. Projemizde yazdığımız kod satırlarının satır numaralarını görmek için aşağıdaki yolu takip edebilirsiniz.
Tools > Options > Text Editor > All Languages Yolu altında bulunan Line Numbers Seçeneği işaretlenir. 1.4.4. Scope Programlarımızda kullandığımız metotlar ve event gibi yapıların kapsayacağı kodları belirler. C Sharp’da scope alanları süslü parantezler ‘{’ İçerisine kodlar ‘}’ ile belirlenir. Aşağıdaki örneği inceleyebilirsiniz.
1.4.5. Syntax Söz dizimi anlamına gelmektedir. Programlama dillerinde kullanacağımız kodların yapısı ve yazım şekli önemlidir. Kod sıralaması, parantez sıraları ve büyük küçük harf duyarlılıklarına syntax denir.
1.4.6. Indent Guides
Visual Studio ortamına daha kolay geliştirme yapmak için eklentiler kurabilirsiniz. Bu eklentiler sizin daha kolay proje geliştirmenize ve kodlarınızı daha kolay okumanıza olanak sağlar. Indent Guides bize scope başlangıç ve bitişlerini gösteren ve açılıp-kapanan scope’ları noktalı çizgiler ile birbirine bağlayan bir eklentidir. Indent Guides kurmak için aşağıdaki adımları takip edebilirsiniz. Sağ tarafta bulunan resimde scope başlangıç ve bitişleri …….. ile işaretlenmiştir.
Tools > Extensions and Updates penceresi açılır. Açılan pencerede sol taraftan ‘Online’ seçeneği seçilir. Visual Studio Gallery içerisinde Indent Guides eklentisini bulup Install butonu ile kurulumu yapabilirsiniz. Kurulumdan sonra Visual Studioyu baştan başlatmanız gerekmektedir. 1.4.7. Intellisence Yazılımcı için en önemli ekranlardan bir tanesidir. Visual Studio’da kod yazarken, intellisense penceresi işlerimizi kolaylaştırır. Intellisense bizim kodlarımızı hazır olarak tamamlayan bir penceredir. Kod yazmayı kolaylaştırır ve daha doğru kod yazmamızı sağlar.
22 | S a y f a
Örneğin; biz kod yazarken bir kod’un baş harflerinden birkaç tanesini yazdığımızda baş harfi aynı olan ve referanslarımızda kayıtlı olan kodların listesini bize sunar.
Intellisense penceresi kapandığında, CTRL + Space tuş kombinasyonu ile tekrar açabilirsiniz.
1.4.8. Tooltip Yazılımcının okumasını bilmesi gerektiği ekrandır. Program geliştirirken yazılan kodların nasıl kullanması gerektiğini bildirir. Doğru kullanıldığı taktirde bir yazılımcı için en önemli penceredir. Sol üst kısımda, yapının Geriye dönüş tipini gösterir. Alt Kısımda içerisine aldıgı parametrelerle ilgili bilgiler yer alır. Kodların yapısını okuyarak nasıl kullanılması gerektiği ile ilgili bilgi verir.
1.4.9. Smart Tag
Bazı kontrollerin çok kullanılan özelliklerini Smart Tag penceresinde bulunur. Belirli kontrollerin en çok kullanılan özelliklerine daha hızlı erişim kolaylıgı sağlar.
1.5. YAZILIMA GİRİŞ
Artık yavaş yavaş kod tarafına geçme vaktimiz geldi. İlk kod örneğimizi yazmadan önce bir takım kuralları bilmemiz gerekiyor. C Sharp’da dikkat edilmesi gereken kurallar;
C Sharp programlama dilinde, satır sonları ';’ ile işaretlenir. Bu işaret kod satırının bittiği anlamına gelir. C Sharp dilinde söz dizimine Syntax denir. Syntax dilin belirli kurallarının olması ve kod yazarken bu kurallara uyulması gerektiğidir. Eğer biz bu kurallara uymadan kodlarımızı yazmaya çalışırsak Syntax hataları alırız. İleri ki konularda Syntax’ı detaylı inceleyeceğiz.
Kod yazmaya başlamadan önce birkaç terimi bilmemiz gerekiyor.
1.6. EVENTS – OLAYLAR
Event, belirli bir olayda veya belirli bir zamanda meydana gelen yada meydana gelmesini istediğimiz işlemleri tasarlayacağımız olayların bütünüdür. Eventler, bir kontrolü kullanmamız için gereken zaman kavramlarıdır. Kullanacağımız kontrolün zaman kavramlarını yöneterek kod yazabiliriz.
Bizler kontrolün zaman kavramlarını çok iyi bilmeliyiz. Örneğin bir TextBox’ın eventlerinden bahsedecek olursak; TextChanged : Textbox içerisinde girilen yazı değiştiğinde hangi kodların çalışacağı yazılır.
23 | S a y f a
MouseDoubleClick : Mouse ile çift tıklandığında hangi kodların çalışacağı yazılır. MouseMove : Mouse ile Textbox üzerinde hareket edildiğinde yapılacak kodlar yazılır.
Yukarıda bahsettiğimiz kontrollerin eventlerinde zaman kavramına dikkat etmemiz gerekir. Altı çizili olan yazılarda bir zaman kavramı bulunmaktadır. 1.6.1. Event Mantığı
Bir programcı zaman kavramlarını çok iyi biliyor ve bu zaman kavramlarını çok iyi yönetebiliyor olmalıdır.
Programlamanın temelinde iki soru vardır. Bu iki sorunun mantığı tam olarak kavrandığında kod yazmak çok kolaylaşacaktır.
Soru 1 : Ne zaman yapacağım? Soru 2 : Ne yapacağım?
Yukarıdaki soruları bir örnek ile açıklayalım. Soru 1 : Ne zaman yapacağım? Örnek Cevap : Butona tıklandığı zaman Soru 2 : Ne yapacağım? Örnek Cevap : Kullanıcıya mesaj göstereceğim. Yukarıdaki soru ve cevap örneğini incelemek için aşağıdaki adımları uygulayabiliriz.
Örnek Kod: Kod yazmaya başlamadan önce yeni bir proje oluşturmamız gerekiyor. Visual Studio programını çalıştırdıktan sonra, yeni bir proje oluşturuyoruz. Proje oluşturma hakkında detaylı bilgiye önceki konularımızda değinmiştik.
Bizim Windows Form Application olarak oluşturduğumuz proje bize Form1 isminde bir form ekranı sunar. Form1 ekranının Code Behind sayfasına ulaşmak için F7 tuşuna basmamız yeterlidir.
24 | S a y f a
İlk kodumuzu yazmak için formun Design alanına gelip form’a çift tıklıyoruz. Forma çift tıkladığımızda bize Formun Event’lerinden Load eventini (Form Yüklenirken) Code Behind sayfasına oluşturur.
Dikkat ettiyseniz Form Load eventinin Formun yüklenirken çalışacak olan eventi olarak bahsettik. Formun yüklenmesi sırasında işleyecek kodlar load eventinde yazılır.
İlk Eventimizi Oluşturduk //Form'a çift tıkladığımızda aşağıdaki kodlar oluştur. private void Form1_Load(object sender, EventArgs e) { }
Yukarıdaki kod satırı ekranda bir mesaj penceresi içerisinde “Hello World” yazısını yazdırır. Biz kullanıcıya mesajlar göstermek istediğimizde yukarıdaki kod satırını kullanabiliriz. Yukarıda ki kod satırını çalıştırdığımızda Resim 2.1’de bulunan görüntü gibi bir sonuca ulaşırız.
Kullanıcıya mesaj görüntülendikten sonra “Tamam” butonuna basarak bu pencereyi kapatabiliriz. Burada ki buton isimlerinin Türkçe veya İngilizce olması işletim sisteminin diliyle ilgilidir.
1.6.2. Event Detayları Her kontrole ait onlarca event bulunmaktadır. Bu eventleri çalıştırmak için ilgili kontrolü mouse ile seçtikten sonra Properties penceresinden Eventler sayfasına geçmeliyiz.
Events sekmesinde listelenen eventler, o kontrole ait olan event listesidir. Bizler bir kontrolün zaman kavramını eventler ile yönetebiliriz. (Örneğin textbox’a veri girildiği zaman)
Herhangi bir kontrolün üzerine çift tıkladığımızda, Visual Studio tarafından tanımlı olarak o kontrole ait en çok kullanılan event Code Behind sayfamızda oluşur.
Örnek ; 25 | S a y f a
Event mantığını kullanarak küçük bir alıştırma yapalım ve alıştırmamız sırasında atama operatörlerini inceleyelim.
Çok basit bir örnek ile başlayalım. Öncelikle Resim 2.2 de ki görünümü elde edelim.
Hazırladığımız projede yapmak istediğimiz, Checkbox kontrolüne tıklandıkça butonun aktifliğini değiştirmektir. Biz checkbox kontrolünü işaretlediğimizde buton aktif olacak, işareti kaldırdığımızda ise pasif olacaktır.
Bu işlemi yapabilmek için öncelikle checkbox kontrolünün seçiminin değiştiği zamanı kontrol eden eventi bulmalıyız. Checkbox kontrolünde bu işi üstlenen event “CheckedChanged” eventidir. Checkbox işaretlendiğinde ve işaret kaldırıldığında bu event çalışır.
Checkbox kullanıcıdan seçimler yapmasını istediğimizde kullandığımız bir kontroldür. Aşağıdaki kodları Checkbox kontrolümüzün CheckedChanged eventine yazmamız gerekmektedir.
= (eşittir) C Sharp’da atama operatörü olarak kullanılmaktadır. Sağdaki değeri sol tarafa atar. Buradaki önemli nokta birbirine eşitlenebilir değerler birbirine eşitlenebilirdir.
1.7. VARIABLES (DEĞİŞKENLER)
Bizler projelerimizde her zaman sabit verilerle çalışmayız. Kullanıcıdan veri almamız gereken durumlar olabilir veya biz projemiz çalışırken bazı verileri değiştirmek isteyebiliriz. İşte böyle bir durumda kullanabileceğimiz yapılar olan “Değişken”leri kullanırız.
Değişken, verilerimizi ram üzerinde saklayan alanlardır. Biz bilgisayarlarımızda yaptığımız her işlemi RAM isimli parça üzerinden yaparız.
Random Access Memory (RAM) 26 | S a y f a
Bilgisayarın donanım bileşenlerindendir. Mikroişlemcili sistemlerde kullanılan bir tür veri deposudur. RAM geçici bir hafıza birimidir. Bilgisayar çalıştığı süre boyunca üzerinde veri tutabilir. RAM’de ki güç kesildiğinde (Bilgisayar kapatıldığında) RAM, üzerinde bulunan tüm bilgileri kaybeder. RAM’in amacı bizler bilgisayarlarımızda işlem yaparken, Hard Disk gibi yapıların yavaş çalışmasından dolayı, işlemlerde bekleme yaşamamamız için vardır. RAM yapı olarak yüksek hıza sahip olan donanımlardandır. C Sharp’ta tipler Reference Type ve Value Type olarak ikiye ayrılır. Bunlara veri tipleri denir. Veri tipleri, bellekte ayrılacak bölgenin büyüklüğünü belirlemek için kullanılır.
Bir programcının bir dili öğrenmeye başladığında ilk öğrenmesi gereken o dile ait veri tipleridir. Çünkü veri tipleri program içerisinde kullanılacak değişkenlerin ve sabitlerin sınırlarını belirler. C Sharp programlama dilinde veri tipleri türlere ayrılır.
1.7.1. Sayısal/Metinsel Türler
C#'ta hem metinsel hem de sayısal olmayan türler de vardır:
27 | S a y f a
bool Koşullu yapılarda kullanılır. Bool tipi iki değer alır. Bu değerler ‘true’ ve ‘false’ değerleridir.
object Bu değişken türüne her türden veri atanabilir.
Var C# 3.0 da artık tür belirtmeksizin değişken tanımlamamıza olanak sağlayan yenilikler mevcut. Ancak bu değişkenlerin özelliği object değişkenler gibi referans tipli değişkenler değildir. Bunun yerine değeri atanırken tipinin belirlendiği değişkenlerdir.
Datetime İçinde zaman barındıran değişken tipidir. Tür
Boyut
Açıklama
Örnek
DateTime
8 byte
Tarih ve Zaman Tutar
Datetime zaman = Datetime.now
Değişkenler türlerine göre ikiye ayrılır;
1.7.2. VALUE TYPE ve REFERENCE TYPE Değişkenlere giriş yaptığımızda, değişkenlerin Value Type (Değer Tipi) ve Reference Type (Reference Tipi) olarak ikiye ayrıldığını söylemiştik. Yukarıda C Sharp dilinde bulunan veri tiplerinden bahsettik. Şimdi veri tiplerimizin neden ‘Reference Type’ ve ‘Value Type’ olarak ikiye ayrıldığından bahsedeceğiz.
Daha önceki konularımızda RAM’in yapısından bahsetmiştik. RAM temel olarak baktığımızda iki bölümden oluşur. Bu bölümler HEAP ve STACK bölümleridir.
1.7.3. HEAP ve STACK
.Net uygulamalarında kullanılan değişkenlerin ve nesnelerin RAM bellek üzerinde saklandığı alanlardan en temel olanlarıdır. Bu veri alanları .net Framework tarafından yönetilirler. C++ gibi dillerde, değişkenlerin hangi bölümde, ne kadar süre duracağını yazılımcı belirliyordu. Ama yeni nesil programlama dillerinde bu işlem framework tarafından yönetilir. Kullanılan veri tipleri, belirli kurallara göre belleğin ilgili kısımlarında saklanır. 1.7.3.1. STACK RAM belleğin Stack alanında, değer tipleri (int, bool, double, float vb.), Enum ve Struct saklanmaktadır. Belli değer aralıklarına sahip tipler Stack alanında tutulur.
28 | S a y f a
1.7.3.2. HEAP RAM belleğin Heap alanında, referans tipleri (string, object, class, delegate,array) saklanmaktadır. Referans tiplerinin çalışma mantığı aşağıdaki resimde anlatılmıştır.
Biz RAM üzerinde bir değişken oluşturmak için aşağıdaki yapıyı kullanırız.
Yukarıdaki kod ram üzerinde bir değişken oluşturur. string ram üzerinde tutulacak verimizin tipini belirler. Tip belirlemesinden sonra değişken adı belirlenir. ‘=’ ‘den sonra oluşturduğumuz değişkene değer atayabiliriz.
Bir değerleri olmalıdır veya mutlak suretle null olarak tanımlanmalıdır. Değişkenin değeri oluşturulduğu anda verilmek zorunda değildir. Tanımlama yaparken büyük-küçük harf ayrımı vardır. Değişken adları rakamla başlayamaz. Class, namespace ve kontrol isimleri gibi program tarafından kullanılan isimler verilemez. Aynı kod bloğu içerisinde aynı isimden birden fazla değişken tanımlanamaz. Özel karakter içermez örneğin /,*,-,+. Boşluk kullanılamaz. Türkçe karakter kullanılmamalıdır. ş, ğ,ü,ö,ç,ı gibi… Özel sözcükler (if, else, random, vb.) kullanılmaz.
string degisken = textBox1.Text; //Textbox'dan gelen değeri, değişkenimize aktarıyoruz. }
1.7.4. Local ve Global Değişkenler C Sharp’da oluşturduğumuz yapıların scope alanlarına göre erişilebilirlik durumları vardır. Bunlara yaşam alanı denir. Bir event içerisinde tanımlanan bir değişkene başka bir event içerisinden erişemeyiz. Bir değişkene birden fazla event içerisinde erişmek istediğimizde değişkeni scope alanları dışarısında yani global alana tanımlamamız gerekmektedir. Global alan Form içerisinde, eventleri, metotları ve diğer yapıları tanımladığımız, proje derlendiğinde RAM’e ilk çıkartılacak yapıları belirleyen zaman kavramından uzak yapıdır. İçerisinde eventler, metotlar ve proje derlendiğinde RAM üzerine çıkartılmasını istediğimiz yapıları tanımlayabiliriz. 1.7.4.1. Local Değişkenler Belirli bir event veya metoda bağlı değişkenlerdir. Yaşam alanları (erişilebilecek yer) sadece bağlı oldukları scope alanlarıyla sınırlıdır. Örneğin Formun Load eventinde tanımladığımız bir değişkene başka bir eventten erişemeyiz.
1.7.4.2. Global Değişkenler Bir değişkene, birden fazla event’den veya metotdan ulaşmak istediğimizde tanımlama yerini değiştirmemiz gerekebilir. Global değişkenler proje derlenirken RAM bellek üzerine çıkartılır ve program sonlanana kadar RAM üzerinde yaşamaya devam ederler. Global değişkenlere Form içerisinde birden fazla yerden erişilebilir.
Global Değişken Tanımlama public partial class Form1 : Form { public Form1() { InitializeComponent(); } //Global Değişken Tanımlama string globalDegisken = "Bu Global Bir Değişkendir."; //Forma çift tıklayarak Load Eventini oluşturabiliriz. private void Form1_Load(object sender, EventArgs e) { globalDegisken = "Formun Load Eventinden Global'de Tanımlanan Değişkene Erişebiliriz."; } //Form üzerine bir adet button ekleyip, üzerine çift tıklayarak Buttonun Click eventini oluşturabiliriz.
Yazıldığı yerin sağında bulunan değer, eşittirin soluna aktarılır. Yukarıdaki örnekte Textbox kontrolünün Text özelliğinde ki (Property) değer string tipindeki değişkenimize aktarılmıştır.
Atama Operatöründe dikkat edilmesi gereken çok önemli bir nokta vardır. SADECE EŞİTLENEBİLİR DEĞERLER BİRBİRİNE EŞİTLENİR.
Yani; atama operatörünün solunda bulunan yapı string bir değer istiyorsa, atama operatörünün sağında bulunan değer ise bir string değer taşıyorsa atama işlemi gerçekleştirilir. Eğer atama operatörünün sağında ve solunda bulunan değerler birbirine eşit değilse atama gerçekleştirilemez ve bize Syntax hatası verir.
İki değerin farklı olması durumunda dönüştürme işlemlerini kullanarak iki değer arasında atama gerçekleştirebilir.
1.8. CONVERT İŞLEMLERI
Veri tipler arasında dönüşüm yapmak için kullanılır. Örnek vermemiz gerekirse C# programlama dilinde string ifadeler “çift tırnak” arasında yazılır. Aynı zamanda “23” de bir string ifadedir. Ama 23 aynı zamanda bir sayıdır. 23 ifadesini çift tırnak içerisine aldığımızda string ifade elde etmiş oluruz. Ancak biz 23 sayısını bir matematiksel işleme tabi tutacağımız zaman, 23 değerini sayı olarak elde etmeliyiz.
Kullanıcı Textbox kontrolünü kullanarak bir sayı girişi yaptığında, bu değer C# tarafına string bir ifade olarak yansır. Bizim bu ifadeyi integer bir ifadeye dönüştürmemiz gerekir.
Dönüştürme İşlemi int sayi = Convert.ToInt32(textBox1.Text);
Yukarıdaki kod textboxdan gelen veriyi, tipi int olan değişkenin içine aktarır. Eğer Textbox’ın Text Özelliğinde (kullanıcının girdiği değer) bir sayı ise yukarıda ki kod bloğu hatasız olarak çalıştırılacak ve kullanıcının string tipte girdiği sayıyı integer(sayısal) olarak elde etmiş olacağız.
1.9. HATA YÖNETIMI 1.9.1. Exception Handling Hata yönetimidir. Yazılımcılar farklı türlerde, bir çok hata ile karşılaşabilirler. Önemli olan nokta karşılaştığımız hataları çözebilmek ve bu hataları kısa sürede doğru bir şekilde kontrol altına alabilmektir. Bir hata ile karşılaştığımızda bu hataların öncelikle ne tür bir hata olduğunu bilmemiz gerekmektedir. Hatalar kendi içerisinde gruplara ayrılır.
1.9.2. Syntax Errors (Derleme Zamanı Hataları)
Syntax hataları, bir yazılımcının en çok karşılaşacağı hata çeşitidir. Hatayı bulmak ve yönetmek kolaydır. Error List penceresinde hata mesajı görünür. Syntax Hatalarını düzeltmediğimiz zaman program çalışmayacaktır.
Gelişmiş bir IDE olan Visual Studio anlık olarak kodlarımızı kontrol edecek ve bize yardım edecektir.
1.9.3. Runtime Errors (Çalışma Zamanı Hataları)
Programda bir syntax hatası olmamasına karşı, kullanıcının yanlış bilgi girmesi veya programcının kontrol altına almadığı bir durum sonucu karşılaşılan hatalardı. Bu tür hatalardan korunmak için kullanılan yapılar bulunmaktadır.
1.9.4. Logical Errors – Mantıksal Hatalar
Mantıksal hatalar, tespit edilmesi en zor hata çeşitidir. Syntax olarak hata vermemekle birlikte, runtime hataları gibi programda bozukluğa sebep olmaz. Yazdığımız kodlar istediğimiz sonucu döndürmüyorsa Mantıksal bir hata ile karşı karşıya olabiliriz. Mantıksal hataları tespit etmek için Runtime sırasında kodlarımızı adım adım kontrol etmemiz gerekebilir.
Hata çeşitlerini incelediğimize göre şimdi sırasıyla bu hataları nasıl yönetebilir ve kontrol altına alabiliriz bunu inceleyelim. İlk olarak hatalar içerisinde en kolay tespit edilen grup olan Syntax Hatalarını nasıl giderebileceğimizi inceleyelim.
Projeyi derlediğimizde proje içerisinde bir syntax hatası bulunuyorsa (noktalı virgül unutmak, scope kapatmamak, yanlış değerleri eşitlemek vb.) Error List penceresinde
32 | S a y f a
Syntax hatalarımız görünür. Yapmamız gereken, hata satırını okumak ve hata satırı üzerine çift tıklayarak hata veren kod satırını görüntülemektir.
1.9.5. Error List Syntax hatalarımızı görüntüleyebileceğimiz penceredir. Projeyi derlediğimiz zaman projede ki syntax hataları Error List penceresinde görüntülenecektir.
İlgili Hatanın üzerine çift tıklayarak hata veren satırı (Kırmızı ok ile işaretlenmiş) görüntüleyebiliriz. Verilen hata mesajına göre (Yeşil ok ile işaretlenmiş) hatamızı düzeltebiliriz. Error List penceresi bize projemizde kaç adet hata olduğu (Lacivert ok ile işaretlenmiş) bilgisinide verir.
Error List penceresinde hatalarımız dışında Warnings sekmesi altında uyarılarda görünür. Warnings sekmesinde çıkan mesajlar hata değildir. Projemiz içerisinde bulunan kodlar hakkında bize uyarı verirler. Örneğin bir değişken oluşturduysak ve bu değişkeni kullanmadıysak, RAM’de gereksiz yer kapladığı bilgisini verir. Projenizin çalışmasına engel değildir.
1.9.6. Try Catch Finally
Runtime hatalarını yönetmek için kullanılır. Yazılımcının ön göremediği durumlarda hatayı engellemek veya kullanıcı kaynaklı hataları kontrol altına almak için kullanılan yapıdır.
Try Catch Finally bloklarının çalışma mantığı, Try blokları içerisinde bulunan kodlarda herhangi bir sebepten hata oluşursa, Try bloğundaki kod akışı durur ve kod akışı Catch bloğundan devam eder. Catch bloğundaki kodlar işlendikten sonra Finally bloğu çalıştırılır. Genellikle Finally bloğunda temizleme, form düzenleme gibi işlemler yapılır.
Try Catch Finally yapısında Try ve Finally bloğu mutlaka çalışır. Catch bloğu yanlızca Try bloğunda oluşacak hata sonucunda çalışacaktır.
Try Catch Finally Blokları try { string deger = "5"; int sayi = Convert.ToInt32(deger); //Eğer gelecek değer bir sayı ise dönüştürme işlemi başarıyla gerçekleşecektir. Eğer deger değişkeninden gelen bir harf veya farklı bir karakter ise kod bloğu hata verecektir. } catch { //deger değişkeninden bir harf veya özel karakter geldiğinde catch bloğu çalışmaya başlar. MessageBox.Show("Lütfen sayı girin."); } finally { //Form Temizleme //Textbox Odaklanma //gibi işlemler yapılır. }
Try Catch Kullanımı – Hatayı Özelleştirme try { double sayi1 = Convert.ToInt32(txtSayi1.Text); double sayi2 = Convert.ToInt32(txtSayi2.Text); double sonuc = sayi1 / sayi2; lblSonuc.Text = sonuc.ToString(); } catch (FormatException ex) // Format Hatası olduğunda hata verir. { MessageBox.Show("Lütfen doğru formatta veri giriniz."); } catch (OverflowException ex) //Değişken sınırları dışına çıktıgında hata verir { MessageBox.Show("Değişken sınırları dışına çıktınız."); } catch (DivideByZeroException ex) //Sayıları sıfıra bölmeye çalışırsan yakalar { MessageBox.Show("Sıfıra bölünme hatası .. Sayı Sıfır 'a bölünemez"); } catch (Exception ex) //Geri kalan tüm hataları denetler { MessageBox.Show(ex.Message); }
Exception ex kod satırındaki ex catch bloğunun özelliğidir.. Bu özellik içerisinde karşılaşılan hata ile ilgili tüm bilgileri tutar. MessageBox.Show(ex.Message); gibi bir komutla çalıştırdıgımızda yakalanan hatanın mesajını kullanıcıya gösterir. Tüm catch bloklarında hataları ex ismi ile yakalıyoruz. Aynı isme sahip başka ex’ler olmasına
34 | S a y f a
rağmen diğer catch blokları ile çakışmamasının sebebi, her bir ex özelliği kendi scope’u ile ilgilidir. Kullanılan her ex özelliği kendi scopelarında çalıştığı için birbirleriyle çakışmazlar.
1.9.7. Break Point
Break Point (Duraklama Noktası) debug işlemi sırasında kod akışını takip edebileceğimiz ve Runtime’da dönen değerleri program çalışırken izleyebileceğimiz özelliktir. Proje çalışırken verileri anlık olarak izlememize hangi kod satırında hangi işlem yapıldığını program çalışırken incelememize olanak tanır.
İzlemeye almak istediğimiz kod’u break point ile işaretlememiz gerekmektedir. Kod akışı sırasında, sıra break point ile izlemeye almak istediğimiz satıra gelince, visual studio’da ki kod ekranı açılacaktır. Bizler break point kısayolları ile değerleri program çalışırken inceleyebiliriz.
F10 : Kod akışını takip etmeksizin izlemeye alır. Her tıkladığımızda satır satır kod akışı ilerleyecektir. F11 : Kod akışını takip ederek izlemeye alır. Uygulamadı ki kod akışını takip ederken, kod akışı farklı bir event veya metoda yöneliyorsa kod akışını izlemeye devam eder. Shift + F11 : Kod bloğunda ki akışı bitirir.
1.10. OPERATÖRLER
Matematiksel veya mantıksal işlem yapmamız gereken durumda operatörleri kullanabiliriz. Operatörler Matematiksel Operatörler, Mantıksal Operatörler, Arttırma Operatörleri, Birleşik Operatörler ve İlişkisel Operatörleri olmak üzere gruplara ayrılır.
1.10.1.
35 | S a y f a
Aritmetik Operatörler
1.10.1.1. Matemetik Operatörleri
Operatör +
İşlem Toplama İşlemi
Görevi
-
Çıkartma İşlemi
*
Çarpma İşlemi
/ %
Bölme İşlemi Mod Alma İşlemi
Verilen sayıları matematiksel toplama işlemine tabi tutar. Verilen sayıları matematiksel çıkartma işlemine tabi tutar. Verilen sayıları matematiksel çarpma işlemine tabi tutar. Verilen sayıları matematiksel bölme işlemine tabi tutar. Sayının x’e bölümünden kalanı verir.
1.10.1.2. Arttırma Operatörleri
Operatör Sayi++
İşlem Arttırma
Sayi--
Azaltma
++sayi
Arttırma
--sayi
Azaltma
Görevi Yanına yazıldığı sayının değerini 1 arttırır. Başka işlem varsa önce sayıyı arttırır ve daha sonra işleme devam eder. Yanına yazıldığı sayının değerini 1 azaltır. Başka işlem varsa önce sayiyi azaltır ve sonra işleme devam eder. Yanına yazıldığı sayının değerini 1 arttırır. Başka işlem varsa önce o işlemi yapar ve sayıyı sonra arttırır. Yanına yazıldığı sayının değerini 1 azaltır. Başka işlem varsa önce o işlemi yapar ve sonra sayıyı azaltır.
1.10.1.3. Birleşik Operatörler
Operatör +=
İşlem Topla ve Aktar
-=
Çıkart ve Aktar
*=
Çarp ve Aktar
/=
Böl ve Aktar
1.10.2. Operatör 36 | S a y f a
Görevi Toplama işlemlerini daha kısa yoldan yapmak için kullanılan operatörlerdir. Görevi “sonuc = sonuc + 5” gibi bir ifadeyi kısa yazmaktır. “sonuc += 5” dediğimizde iki ifade aynı işlemi yapacaktır. Bunun dışanda string birleştirme içinde kullanılabilir. Çıkarma işlemlerini daha kısa yoldan yapmak için kullanılan operatörlerdir. Görevi “sonuc = sonuc – 5” gibi bir ifadeyi kısa yazmaktır. “sonuc -= 5” dediğimizde iki ifade aynı işlemi yapacaktır. Bunun dışanda string birleştirme içinde kullanılabilir. Çarpma işlemlerini daha kısa yoldan yapmak için kullanılan operatörlerdir. Görevi “sonuc = sonuc * 5” gibi bir ifadeyi kısa yazmaktır. “sonuc *= 5” dediğimizde iki ifade aynı işlemi yapacaktır. Bunun dışanda string birleştirme içinde kullanılabilir. Bölme işlemlerini daha kısa yoldan yapmak için kullanılan operatörlerdir. Görevi “sonuc = sonuc / 5” gibi bir ifadeyi kısa yazmaktır. “sonuc /= 5” dediğimizde iki ifade aynı işlemi yapacaktır. Bunun dışanda string birleştirme içinde kullanılabilir.
Mantıksal Operatörler İşlem
Görevi
&
Ve
&&
Mutlak Ve
|
Veya
||
Mutlak Veya
^
Özel Veya
1.10.3.
Bu Operatör her iki operandın değerlerini alır ve her iki operand da doğru olmadığı sürece yalnış sonucunu üretir. Doğru sonucunu vermesi için her iki operandın doğru olması gerekir. Normal & operatörlerinden tek farkı normal operatörlerin her iki operandı da önermeye dahil etmesiyken, && operatörünün sadece gerektiğinde diğer operandlara bakmasıdır. Herhangi birinin doğru olması, doğru sonucunu üretmek için yeterlidir. Sadece ve sadece iki operandın yalnış olması halinde sonuç yalnıştır. Normal | operatörlerinden tek farkı normal operatörlerin her iki operandı da önermeye dahil etmesiyken, koşullu operatörlerin sadece gerektiğinde diğer operandlara bakmasıdır. Normal | operatörlerinden tek farkı normal operatörlerin her iki operandı da önermeye dahil etmesiyken, || operatörünün sadece gerektiğinde diğer operandlara bakmasıdır.
İlişkisel Operatörler
İlişkisel operatörler boolean sonuç döndürür.
Operatör == != >
İşlem Eşit Mi Eşit Değil Mi Büyük Mü
<
Küçük Mü
>=
Büyük Eşit Mi
<=
Küçük Eşit Mi
Görevi Verilen iki değerin eşit olma durumunu kontrol eder. Verilen iki değerin eşit olmama durumunu kontrol eder. Birinci değerin, ikinci değerden kontrol eder. Birinci değerin, ikinci değerden kontrol eder. Birinci değerin, ikinci değerden durumunu kontrol eder. Birinci değerin, ikinci değerden durumunu kontrol eder.
büyük olma durumunu küçük olma durumunu büyük veya eşit olma küçük veya eşit olma
1.11. RANDOM SINIFI
Rasgele sayı üretmemiz gereken durumlarda kullanabileceğimiz sınıftır. Rasgele sayı üretme işlemi, bilgisayardan veriler toplayarak bu verilerin belirli bir algoritmadan geçirilerek sayı doğrusu üzerinde belirttiğimiz değerler arasında bize bir sayı üretmesi sonucuyla oluşur. Bilgisayarda rasgele diye bir işlem yoktur. Tüm bilgi ve veriler belirli bir algoritma sonucu üretilir. Rasgele dediğimiz işlem bilgisayardan toplanan bilgilerin (Bilgisayarımızın, ram doluluğu, işlemci ısısı, ram çalışma hızı, hard disk doluluk oranı, ekranın yineleme hızı vs.) algoritmaya alınması ve sonuç üretmesi durumudur.
Random Kullanımı private void button1_Click(object sender, EventArgs e)
37 | S a y f a
{ Random rnd = new Random(); int rasgelesayi = rnd.Next(); //Rasgele bir sayı üretir. int sayi1 = rnd.Next(50); //0 ile verdiğimiz değer arası bir sayı üretir. int sayi2 = rnd.Next(20, 100); //Belirttiğimiz iki değer arası sayı üretir. }
1.12. DATETIME SINIFI
Tarih ve saat formatında bilgi tutabileceğimiz sınıftır. Çeşitli formatlarda tarih bilgisi tutabiliriz. Tarih bilgisinin içerisinden istediğimiz değeri çekebilir, istediğimiz formatta bilgileri gösterebiliriz. DateTime sınıfında veri tutmak için;
Yukarıdaki kod bloğu formun açıldığı tarih ve saati, RAM üzerinde tarih ve saat tipinde tutar. DateTime TarihSaat; ram üzerinde tipi DateTime olan bir TarihSaat nesnesi oluşturur. DateTime.Now komutu ise sistemin şu anki saatini bize verir.
1.12.1.
Timer Kontrolü
Milisaniye cinsinden belirtilen zaman aralıklarında kodlarımızı çalıştırmak için kullandığımız kontroldür. Örneğin bir işlemin 10 saniyede bir kez yapılmasını istediğimizde kullanabiliriz. Bu işlemi yapmak için kullanıcının herhangi bir butona tıklaması gerekmez. Timer kontrolü otomatik olarak 10 saniyede bir çalışacaktır. Aşağıdaki projeyi geliştirebilmek için timer kontrolünü kullanacağız. Timer kontrolü çalışırken kullanıcı başka işlemler yapabilir.
Timer içerisinde çalıştırılacak kodlar Timer’ın Tick eventi içerisinde yazılır. Timer ile ilgili bazı ayarları aşağıda görebilirsiniz.
Timer ile İlgili Ayarlar timer1.Start(); //Timer’ı çalıştırmak timer1.Stop(); //Timer’ı durdurmak timer1.Interval = 10000; //Timer’ın kaç milisaniyede bir çalışacağı..
Örnek Uygulama
38 | S a y f a
Bir proje oluşturalım. Oluşturduğumuz proje bize tarih ve saat bilgisini anlık olarak göstersin. Bunun için formumuza 10 adet label ve 1 adet Timer kontrolü ekleyelim.
Örnek Uygulama private void Form1_Load(object sender, EventArgs e) { timer1.Start(); //Timer’ı çalıştırmak } //Timer Kontrolünün Tick Eventi private void timer1_Tick(object sender, EventArgs e) { lblGorunum1.Text = DateTime.Now.ToString(); //Şu anki tarih ve saati Bilgisini Verir. lblGorunum2.Text = DateTime.Now.ToShortTimeString(); //Saat:Dakika Bilgisini Verir. lblGorunum3.Text = DateTime.Now.ToShortDateString(); // Gün.Ay.Yıl Bilgisini Verir. lblGorunum4.Text = DateTime.Now.ToLongTimeString(); // Saat:Dakika:Saniye Bilgisini Verir. lblGorunum5.Text = DateTime.Now.ToLongDateString(); //Tarih ve Saat Bilgisini Detaylı Verir. }
1.13. KARAR YAPILARI
C Sharp programlama dilinde, kod akışı yukardan aşağıya doğru hiç bir satır atlanmaksızın devam eder. Ama programcıların bazı durumlarda kod akışına yön vermesi gerekebilir. İşte bu tür durumlarda kod akışına yön vermek için kullanacağımız yapılara Karar Yapıları denir.
Verilen şarta göre, kod akışına yön verebiliriz yani istediğimiz kodları programdan saklayabilir veya istediğimiz kodları çalıştırabiliriz.
1.13.1.
IF Else – Else IF
En çok kullanılan karar yapısıdır. Tüm gelişmiş programlama dillerinde karar yapıları bulunmaktadır. Verdiğimiz şarta göre; Şart sağlanıyorsa : istediğimiz kodları çalıştırabiliriz. Şart sağlanmıyorsa : belirttiğimiz kodlar program tarafından okunmadan geçilir.
IF Else yapısı verilen şartları tek tek kontrol ederek, şartın sağlandığı durumda işlemleri gerçekleştirir. Bir örnekle açıklayalım; BilgeAdam’da şubeye geldiniz. İlk ders gününüzde Lab’ınızı bulmanız gerekiyor. Sadece Lab bilgisine sahipsiniz. Lab’ın hangi katta olduğunu bilmediğinizden tek tek Lab’ları dolaşıp, dersinizin olduğu Lab’ı bulmanız gerekir. Her Lab’a baktığınızda elinizde ki Lab bilgisi ile kapıda yazan Lab bilgisini karşılaştırırsınız ve doğru sonuca ulaşana kadar bu işlem devam eder.
39 | S a y f a
IF karar yapısında Mantıksal operatörler ve ilişkisel operatörler kullanılır. Mantıksal opearatörler birden fazla ilişkisel operatör ile dönen sonuçlarda karar vermek için kullanılır.
Senaryo: Dışarıdan girilen sayının teklik çiftlik durumuna göre kullanıcıya mesaj verecek olan karar mekanizması;
40 | S a y f a
Else IF; Tek bir karar yapısı içerisinde if ve else durumları dışında farklı durumlar oluşuyorsa ve bu durumları kontrol altına almak istiyorsak else if basamağını kullanabiliriz. IF- Else IF – Else yapısının çalışma mantığı aşağıdaki gibidir.
İlk olarak ifade1 kontrol edilir; bu ifade doğru ise, 1. şart sonucunda yapılması gereken işlemler uygulanır. İfade1 yanlış ise, ifade2 kontrol edilir. Bu ifade doğru ise, bu durumda sadece 2. şart sonucunda yapılması gereken işlemler uygulanır. İfade2 yanlış ise, o takdirde, ifade3 kontrol edilir. Bu ifade doğru ise, bu durumda sadece 3. şart sonucunda yapılması gereken işlemler uygulanır.
IF – Else IF - Else int sayi = 5; if (sayi == 3) //Sayı 3'e Eşitse { MessageBox.Show("Sayı 3'e eşittir."); } else if (sayi < 3) //Sayı 3'den küçükse { MessageBox.Show("Sayı 3'den küçüktür"); } else //Sayı eşit veya küçük değilse else basamağı çalışır { MessageBox.Show("Sayı 3'den büyüktür."); }
Mantıksal Operatörler 3 < 10 && 3<15 (3 sayısı, 10 ve 15 sayısından küçüktür.) Yukarıdaki işlemde 3 < 10 True sonucu döndürür. 3 < 15 True sonucu döndürür.
&& operatörü ile bu iki işlemden dönen sonuç true olduğunda karar yapımıza true sonucu dönecektir.
Senaryo: Dışarıdan girilen not 0 - 30 araligi ise "FF" 30 - 50 araligi "DD" 50 - 70 "BB" 70 - 100 "AA" aldınız seklinde kullaniciya uyarı veren uygulama;
41 | S a y f a
1.13.2.
Switch Case
Kullanım alanı if yapısına göre daha az olan switch case yapısı, if yapısından daha hızlı çalışır. Switch case kullanarak yapabileceğimiz tüm işlemleri IF Else – Else IF karar yapısı ile yapabiliriz. Fakat kullanılabildiği durumlarda Switch Case daha fazla performans sağlayacaktır.
42 | S a y f a
Switch Case verilen değeri yapı içerisinde işaretleyerek gelen değere göre doğrudan yönlendirme yapar. IF Else yapısında verdiğimiz örneği Switch Case için açıklayalım.
İlk ders gününüzde Lab arıyorsunuz. IF Else yapısında ki gibi tek tek Lab’ları kontrol etmek yerine danışmaya sorarak kesin bir bilgiyi hızlı bir şekilde elde edebilirsiniz.
Switch Case ile IF else arasında ki fark kısaca böyle ifade edilebilir. Switch Case ile ilgili aşağıdaki örneği inceleyelim. Örnekte bulunan formun tasarımına geçelim. İki adet Textbox, bir adet ComboBox ve bir adet Button kontrolünü formumuza ekleyelim. Kontrollerin property penceresinden ayarlarını aşağıdaki gibi düzenleyin.
Button Özellikleri;
Name : btnHesapla Text : Hesapla
ComboBox Özellikleri
Name : cbOp Items : Açılan pencereye alt alta ‘+’ ‘-‘ ‘x’ ‘/’ karakterlerini yazınız DropDownStyle : DropDownList
Yukarıdaki form ekranlarını elde ettikten sonra aşağıdaki gibi kodlarımızı yazmaya başlayabiliriz.
Switch Case Örnek Uygulama //Buttonun Click Eventi private void btnHesapla_Click(object sender, EventArgs e) { int sonuc = 0; //Sonucu tutacağımız değişken switch (cbOp.SelectedText) { case "+": //Eğer ComboBox'da Toplama işlemi seçildiyse sonuc = Convert.ToInt32(txtSayi1.Text) + Convert.ToInt32(txtSayi2.Text); break;
43 | S a y f a
case "-": //Eğer ComboBox'da Çıkarma işlemi seçildiyse sonuc = Convert.ToInt32(txtSayi1.Text) - Convert.ToInt32(txtSayi2.Text); break; case "x": //Eğer ComboBox'da Çarpma işlemi seçildiyse sonuc = Convert.ToInt32(txtSayi1.Text) * Convert.ToInt32(txtSayi2.Text); break; case "/": //Eğer ComboBox'da Bölme işlemi seçildiyse sonuc = Convert.ToInt32(txtSayi1.Text) / Convert.ToInt32(txtSayi2.Text); break; } MessageBox.Show("Sonuç : " + sonuc); //Sonucu Kullanıcıya Göster }
1.13.3.
Ternary IF
IF ve Else bloklarından oluşur. IF yapısını tek satırda yazmak için kullanabiliriz. Kod yapısı biraz değişmekle birlikte IF ve Else yapısından bir farkı yoktur. Else if durumu bulunmamaktadır. Tek satırda if kontrollerimizi yapmamızı sağlar.
Ternary IF Syntax ? :
Formumuzda bir adet checkbox kontrolü bulunsun. Eğer kullanıcı butona tıkladığında checkbox kontrolünü seçili hale getirdiyse; “Sonuç : True”, seçili hale getirmediyse; “Sonuç : False” mesajı görüntülensin.
Ternary IF Örnek private void button1_Click(object sender, EventArgs e) { MessageBox.Show(chk.Checked ? "Sonuç : True" : "Sonuç : False"); }
Yukarıdaki örneği Ternary IF kullanmadan yapmak istediğimizde aşağıdaki gibi yazmamız gerekirdi.
IF Else Örnek private void button1_Click(object sender, EventArgs e) { if (chk.Checked == true) { MessageBox.Show("Sonuç : True"); } else { MessageBox.Show("Sonuç : False"); } }
44 | S a y f a
1.14. DIZILER (ARRAY) Birden fazla aynı tipteki veriyi bir arada tutmamizi saglayan nesnelerimizdir. EĞER; “Index was outside the bounds of the array.” hatası aliyorsanız, bilin ki dizinin boyutlarını aşacak şekilde eleman ekleme çabasındasınız. Hata nerde diye bakmayın, eleman ekleme işlemlerine gidin!
Dizi Tanımlamaları //1.TANIMLAMA //VeriTipi[] DiziAdi = new VeriTipi[ElemanSayisi]; int[] dizi = new int[3]; dizi[2] = 656; dizi[0] = 5654; dizi[1] = 1321; //dizi[3] = 654674; => Dizimiz 3 elemanlı oldugu icin hata verir! //2. TANIMLAMA //VeriTipi[] DiziAdi = new VeriTipi[ElemanSayisi] { DiziElemanlari } string[] sehirler = new string[4] { "İzmir", "İstanbul", "Ankara", "Eskişehir" }; //3. TANIMLAMA //VeriTipi[] DiziAdi = { DiziElemanlari }; char[] karakterler = { 'a', 'b', 'c', 'd' };
Senaryo; Dizinin son elemanını ekranda gösterelim;
45 | S a y f a
1.15. DÖNGÜLER
Hazırladığımız programlarda bir işi birden fazla kez yapmamız gereken durumlar olabilir. Birden fazla kullanıcıya mail göndermek, belirli iki yıl arasındaki yılları yazdırmak gibi.
Bu tür durumlarda kodlarımızı yapılacak işlem sayısı kadar yazmak yerine döngü yapılarını kullanabiliriz. Belirlediğimiz sayıda aynı işlem gerçekleşecektir.
C Sharp programlama dilinde dört döngü çeşidi bulunmaktadır. Her bir döngünün kendine göre kullanılacağı yerler ve durumlar olabilir.
1.15.1.
For Döngüsü
Bir işi belirli sayıda yapmamızı sağlayan döngüdür. Döngü içerisinde, döngünün başlangıç değeri, bitiş değeri ve artış miktarını berlileyebiliriz.
For döngüsünün yapısı Döngünün Başlangıç Değeri : Döngümüzün hangi değerden başlayacağını belirtiriz. Döngü Bitiş Değeri : Döngünün şartı olarak düşünebiliriz. Döngünün başlangıç ve bitiş değerini kontrol ederek döngümüzün ne kadar çalışacağını belirleyebiliriz. İterasyon : Döngünün başlangıç değerini arttırmak için kullanılır.
For Döngüsü - Syntax for(; ) { //Döngü Her döndüğünde çalışacak kodlar }
Örnek : 0 ile 10 arasındaki sayıları ekrana yazdıran program (10 Dahil Değil) int donguBitisDegeri = 10; //Döngü bitiş değerini belirliyoruz. for (int i = 0; i < donguBitisDegeri; i++) //Döngü Yapısı { MessageBox.Show(i.ToString());//Döngü değerimizi ekrana yazdırıyoruz. }
Yukarıdaki örnek için; forma çift tıklayarak Load event’ini oluşturuyoruz. Yukarıdaki örnekte 0 ile 10 arasındaki sayıları (0 Dahil 10 Dahil Değil) MessageBox ile kullanıcıya gösterdik.
46 | S a y f a
Örnek – 1935 ile 2015 arası yılları ComboBox’a Listeleyen Program private void Form1_Load(object sender, EventArgs e)//Form Çalıştığında { for (int i = 1935; i <= 2015; i++) //2015 yılını dahil etmek için <= kullanıyoruz. { comboBox1.Items.Add(i); } }
Yukarıdaki örnek için; ToolBox’dan formumuza bir adet ComboBox kontrolü ekliyoruz. Daha sonra formun üzerine çift tıklayarak formun Load eventini oluşturuyoruz. Ve yukarıdaki kodlarımızı yazmaya başlıyoruz. Örnek, 1935 ile 2015 yılları arasındaki yılları combobox kontrolüne listeler. Yukarıda şartta kullandığımız <= ifadesini, döngünün başlangıç değeri olan i değişkeninin değerinin 2015’den küçük olduğu veya 2015 e eşit olduğu sürece çalışmasını istediğimiz için kullandık. Sadece < operatörünü kullansaydık 2015 yılı combobox’da ki yıl listesine dahil edilmezdi.
Örnek 2015 ile 1935 arası yılları ComboBox’a Listeleyen Program private void Form1_Load(object sender, EventArgs e)//Form Çalıştığında { for (int i = 2015; i >= 1935; i--) { comboBox1.Items.Add(i); } }
Yukarıdaki örnek için; ToolBox’dan formumuza bir adet ComboBox kontrolü ekliyoruz. Daha sonra formun üzerine çift tıklayarak formun Load eventini oluşturuyoruz. Ve yukarıdaki kodlarımızı yazmaya başlıyoruz. Örnek, 1935 ile 2015 yılları arasındaki yılları combobox kontrolüne listeler. Yukarıda şartta kullandığımız <= ifadesini, döngünün başlangıç değeri olan i değişkeninin değerinin 2015’den küçük olduğu veya 2015 e eşit olduğu sürece çalışmasını istediğimiz için kullandık. Sadece < operatörünü kullansaydık 2015 yılı combobox’da ki yıl listesine dahil edilmezdi.
1.15.2.
While Döngüsü
For döngüsü gibi, bir işi belirli sayıda yapmamızı sağlayan döngüdür. For döngüsünden farklı olarak döngü başlangıç değeri ve iterasyon bilgisi döngü içerisinde belirtilmez.
Örnek – 10 kez dönen While Döngüsü int deger = 0; while (deger < 10) { deger++; }
1.15.3.
Do While Döngüsü
Do while döngüsü, while döngüsü ile aynı yapıya sahiptir. While döngüsünde ki gibi iterasyon ve döngünün başlangıç değeri döngü dışarısında belirtilir. Tek farkı, Do While döngüsü ne olursa olsun en az 1 kez çalışır. Diğer döngüler şart sağlandığında çalışırken, do while döngüsü şart ne olursa olsun bir kez çalışacaktır. Bunun sebebi do while döngüsünde şartın döngünün sonunda kontrol edilmesidir.
Syntax do { //YAPILACAK İŞLEMLER } while ();
1.15.4.
Foreach Döngüsü
Koleksiyon yapılarında kullanılacak bir döngü çeşitidir. Dizi, Generic List gibi yapılarda kullanılır. Foreach döngüsüne müdehale edilemez.
Foreach Döngüsü Örneği private void Form1_Load(object sender, EventArgs e)//Form Çalıştığında { //Dizimizi tanımlıyoruz. string[] ogrenciler = { "Ozan", "Alp", "Tuğberk", "Mustafa", "Murat" }; //Koleksiyon döngüsü Ogrenciler string dizi tipindedir. Her bir öğrencinin tipi stringdir.
48 | S a y f a
foreach (string ogrenci in ogrenciler) { MessageBox.Show(ogrenci);//Ogrenciler içerisindeki her bir öğrenciyi tek tek ekrana yazdırır. } }
1.16. RUNTIME Bizler, projelerimizde belli başlı nesneleri programı hazırlarken oluştururuz. Bu oluşturma işlemini tüm nesnelerimiz üzerinde kullanabiliriz. Fakat kullanıcı programı kullanırken yeni bir nesne oluşturma talebinde bulmak isterse, proje çalışırken yeni bir nesne oluşturmamız gerekebilir. Bunun en güzel örneği Upload sitelerinde sıkça rastladığımız birden fazla dosya seçme işlemi olabilir.
Program Çalışırken bir Button Oluşturma private void Form1_Load(object sender, EventArgs e)//Form Çalıştığında { Button btn = new Button(); }
Yukarıdaki kod bloğunda proje çalıştığında Form yüklenirken yeni bir button oluşturma işlemi yaptık. Yaptığımız işlem kısaca, RAM üzerinde Button tipinde, btn isminde bir nesne yaratmak ve bu nesneye Button sınıfından instance almaktır.
Intance alma işlemi, RAM üzerinde oluşturduğumuz bir nesneye, nesneyi oluşturduğumuz sınıftaki tüm özellikleri aktarmak olarak tanımlayabiliriz. Instance işlemini Object Oriented Programming (Nesneye Yönelik Programlama) konusunda detaylı olarak inceleyeceğiz.
Kısacası ben RAM üzerinde projem çalışırken bir Button tanımlamış oldum. Peki biz bir button açtığımızda Properties penceresinden Button kontrolümüze ait bir çok özelliği değiştirebiliyorduk. Runtime’da oluşturduğumuz bir Button’da property’leri nasıl yönetebiliriz. Şimdi aşağıdaki kod bloğunu inceleyelim.
Buttonun Property’leri Button btn = new Button(); btn.Name = "btnKaydet"; //Buttonumuzun ismi btn.Text = "Kaydet"; //Kullanıcının Göreceği Yazı btn.Width = 200; //Buttonumuzun genişlik değeri btn.Height = 30; //Buttonumuzun yükseklik değeri btn.Location = new Point(30, 50); //Buttonun form üzerindeki konumu btn.Enabled = true; //Buttonun aktiflik durumu
49 | S a y f a
Sorunsuz bir şekilde Property penceresinde bulunan tüm özelliklere btn. Diyerek erişebildik. Peki biz bir buttonun sadece Property’lerinimi kullanabiliyoruz. Peki Runtime’da oluşturduğumuz bir buttonun Eventlerini kullanmak istersek ne yapacağız. Aşağıdaki kod bloğumuzu inceleyelim.
Runtime’da oluşturulan Button’un Eventini Kullanmak private void Form1_Load(object sender, EventArgs e)//Form Çalıştığında { Button btn = new Button(); btn.Click += btn_Click; //Click eventini çağırdıktan sonra += yazar ve TAB tuşuna iki kez basarsak Event Runtime'da oluşturulur. } void btn_Click(object sender, EventArgs e) //Runtime'da oluşturulan Buttonun Eventi { //Yapılacak İşlemler }
1.17. METOTLAR
Bir program geliştirirken, aynı kod bloklarını defalarca kullanmamız gerekebilir. Yazdığımız bir kodu birden fazla event’den kullanmak istediğimizde kullanacağımız her event altına çalışmasını istediğimiz kod bloklarını yazmamız gerekebilir. Böyle durumlarda yazılımcı aynı kodları yazarken vakit kaybetmiş olur. Aynı zamanda birden fazla yerde kullandığımız kodlarda bir değişiklik yaptığımızda her yerde bu değişikliği yapmamız gerekir.
Metotlarda burada bizim yardımımıza koşar. Biz birden fazla yerde kullanacağımız kodları tek bir yapı içerisinde toplarız. Bu yapıyı istediğimiz yerden çağırarak kullanabiliriz. Metotların bizlere bir çok avantajı vardır.
Geliştirilebilir bir yapı sunar. Kod kalabalığını engeller. Tek elden yönetim sağlar. Merkeziyetçi kod yapısı güder.
Metotlar yapılarına göre dört başlık altında incelenebilir.
Geriye Değer Döndürmeyen ve Parametre Almayan Metotlar Geriye Değer Döndürmeyen ve Parametre Alan Metotlar Geriye Değer Döndüren ve Parametre Almayan Metotlar Geriye Değer Döndüren ve Parametre Alan Metotlar
Yapacağımız işlere göre yukarıdaki metot yapılarından birini kullanabiliriz. Metot oluşturmaya başlamadan önce metot oluşturmanın Syntax’ın dan ve Standartlarından bahsedelim.
50 | S a y f a
1.17.1.
Geriye Dönüş Tipi
1.17.2.
Metot İsimlendirme
1.17.3.
Geriye Değer Döndürmeyen ve Parametre Almayan Metotlar
Oluşturacağımız metodun geriye dönüş tipini belirtmeliyiz. Geriye dönüş tipleri metotlar ile yapılmış sözleşmelerdir diyebiliriz. Bir metot oluşturduğumuzda metodun geriye bir değer döndüreceğini belirttiğimizde geriye dönüş sağlamadığımız taktirde hata verir.
Metotları isimlendirirken dikkat etmemiz gereken önemli standartlar bulunmaktadır. Metot isimlerinde kullanılan kelimelerin ilk harfi büyük yazılır ve metot isimleri Emir Kipleriyle yazılmalıdır. Geriye değer döndürmeyen ve parametre almayan bir metodu oluşturmak için öncelikle bilmemiz gereken geriye dönüş tipini belirtmektir. Eğer bir metot geriye dönüş yapmayacaksa bu metot void olarak işaretlenmelidir. Geriye değer döndürmeyen ve parametre almayan bir metodun syntax’ı aşağıdaki gibidir.
Geriye Değer Döndürmeyen ve Parametre Almayan Metotların Syntax’ı () { //Metot içerisinde Yapılacak işlemler //Metot içerisinde Yapılacak işlemler //Metot içerisinde Yapılacak işlemler //Metot içerisinde Yapılacak işlemler }
Geriye Değer Döndürmeyen ve Parametre Almayan Metot Örneği void IkiSayiyiTopla() { int sayi1 = 10; int sayi2 = 15; int sonuc = sayi1 + sayi2; MessageBox.Show(sonuc.ToString()); }
Yukarıdaki kod ile Geriye değer döndürmeyen ve parametre almayan bir metot oluşturduk. Metodun geriye dönüş tipi void olarak işaretlendiğinden bizden bir geriye dönüş beklemedi. Metot içerisinde iki sayıyı toplatıp sonucunu MessageBox ile gösterdik. Biz bu işlemin sonucunu birden fazla event’de göstermek isteseydik tek yapmamız gereken metodu event altında çağırmak olacaktı. Peki bir metodu farklı eventlerde nasıl çağırabiliriz.
Yukarıda ki kod örneğinde Buttonun Click Eventinde, TextBox kontrolünün TextChanged Eventinde ve Formun Load eventinde aynı kodları sadece metodu çağırarak çalıştırmış olduk.
1.17.4.
Geriye Değer Döndürmeyen ve Parametre Alan Metotlar
Bir metot dışardan parametrelerde alabilir. Bunun için metodun syntax’ını incelediğimizde metot adından sonra açıp kapattığımız (parantez) ler içerisinde parametrelerimizi belirleyebiliriz. Metot yanında açılan bu parantezlere ‘Metot Parantezleri’ denir. Eğer metot bir parametre almayacaksa (Geriye Değer Döndürmeyen ve Parametre Almayan metotlarda ki gibi) metot parantezleri açılır ve kapanır. İçerisine herhangi bir parametre tanımlaması yapılmaz. Bir metot sınırsız sayıda parametre alabilir.
Snytax ( ...) { //Metot içerisinde Yapılacak işlemler //Metot içerisinde Yapılacak işlemler //Metot içerisinde Yapılacak işlemler //Metot içerisinde Yapılacak işlemler }
,
Dışarıdan gönderilen iki sayıyı toplayan bir metot yazalım.
52 | S a y f a
Örnek void IkiSayiyiTopla(int sayi1, int sayi2) //Parametre tip ve isimlerini belirtiyoruz. { int sonuc = sayi1 + sayi2; MessageBox.Show(sonuc.ToString()); }
Metodumuzda dışarıdan girilen iki sayıyı toplatmayı amaçladık. Parantezler içerisinde tanımladığımız sayi1 ve sayi2 bizim dışarıdan metodumuza göndereceğimiz parametrelerdir. Peki parametre gönderme işlemini nasıl yapacağız. Metodu birden fazla event altında çağırmayı deneyelim.
Örnek Uygulama //Formun LOAD Eventi private void Form1_Load(object sender, EventArgs e) { //Kullanıcı Sayı Girmediğinde Hata Vermesi Durumunu Kontrol Ediyoruz. try { int kullanicininGirdigiSayi1 = Convert.ToInt32(textBox1.Text); int kullanicininGirdigiSayi2 = Convert.ToInt32(textBox2.Text); IkiSayiyiTopla(kullanicininGirdigiSayi1, kullanicininGirdigiSayi2); //Metodumuzu çağırıyoruz. } catch { MessageBox.Show("Lütfen iki sayı girişi yapınız."); } } //Buttonun Click Eventi private void button1_Click(object sender, EventArgs e) { //Kullanıcı Sayı Girmediğinde Hata Vermesi Durumunu Kontrol Ediyoruz. try { int kullanicininGirdigiSayi1 = Convert.ToInt32(textBox1.Text); int kullanicininGirdigiSayi2 = Convert.ToInt32(textBox2.Text); IkiSayiyiTopla(kullanicininGirdigiSayi1, kullanicininGirdigiSayi2); //Metodumuzu çağırıyoruz. } catch { MessageBox.Show("Lütfen iki sayı girişi yapınız."); } } //TextBox'ın Text Change Eventi private void textBox1_TextChanged(object sender, EventArgs e) { //Kullanıcı Sayı Girmediğinde Hata Vermesi Durumunu Kontrol Ediyoruz. try { int kullanicininGirdigiSayi1 = Convert.ToInt32(textBox1.Text); int kullanicininGirdigiSayi2 = Convert.ToInt32(textBox2.Text); IkiSayiyiTopla(kullanicininGirdigiSayi1, kullanicininGirdigiSayi2); //Metodumuzu çağırıyoruz.
53 | S a y f a
} catch { MessageBox.Show("Lütfen iki sayı girişi yapınız."); } }
Birden fazla event altında aynı metodu çağırdık ve metota değerler göndererek iki sayıyı toplama işlemini gerçekleştirdik.
1.17.5.
Geriye Değer Döndüren ve Parametre Almayan Metotlar
Şu an’a kadar geriye değer döndürmeyen metotları inceledik. Bir metot geriye değer döndürmediğinde void olarak geriye dönüş tipi belirtiyoruz. Peki bir metot geriye bir değer döndürecekse ne yapmamız gerekiyor. Geriye değer döndüren bir metot yazmak için ilk adım geriye dönüş tipimizi belirlemektir..
Syntax () { //Metot içerisinde Yapılacak işlemler //Metot içerisinde Yapılacak işlemler //Metot içerisinde Yapılacak işlemler //Metot içerisinde Yapılacak işlemler }
Bir metot geriye değer döndürecek ise void yerine geriye dönüş tipini belirtmeliyiz. Geriye dönüş tipimiz C Sharp tarafında tanımlı olan veri tipleri (string, int, bool, double vs.) veya bizim tanımladığımız nesne tipleri olabilir. Kendi nesnelerimizi tanımlamayı ilerde inceleyeceğiz.
Örnek olarak bir metot yazalım. Metodumuz dışarıdan isim, soyisim ve doğum yılı bilgisi alsın ve bu bilgiyi MessageBox’da Adınız : {Kullanıcının Girdiği İsim}, Soyadınız : {Kullanıcının girdiği Soyisim}, Yaşınız : {Kullanıcının girdiği doğum yılına göre yaşı hesaplasın} şeklinde göstersin. Öncelikle bu işlem için bir form tasarımı yapalım.
Kullanıcı Bilgileri girdikten sonra butona tıkladığında bilgiler istediğimiz formatta MessageBox’da görüntülensin. Kodlarımızı yazmaya başlayalım. Öncelikle Metodumuzu oluşturalım.
54 | S a y f a
Örnek Uygulama //Butonun Click Eventi private void btnBilgiGoster_Click(object sender, EventArgs e) { string bilgi = BilgiGoster();//Metodumuzu çağırdık. Bize string bir değer döndürdüğü için dönen değeri string bir değişkene aktardık. MessageBox.Show(bilgi);//Dönen bilgiyi ekranda gösterdik. } //Metodumuz string BilgiGoster() { string ad = txtAd.Text; //İsmi değişkene aktardık. string soyad = txtSoyad.Text; //Soyismini değişkene atadık. string dogumYili = txtDogumYili.Text; //Dogum yılını değişkene attık. int yas = DateTime.Now.Year - Convert.ToInt32(dogumYili); //Şimdiki tarihten doğum yılını çıkarıyoruz ve yaşı elde ediyoruz. //String format ile bilgileri gösteriyoruz. return string.Format("Sayın {0} {1}, Yaşınız : {2}", ad, soyad.ToUpper(), yas); //ToUpper() metodu, yazının tamamını büyük harfe çevirir. }
Yukarıdaki kodları çalıştırdığımızda, butona tıklandığında aşağıdaki resimdeki mesaj gösterilecektir.
1.17.6.
Geriye Değer Döndüren ve Parametre Alan Metotlar
Geriye değer döndüren parametre alan metotlar, girilen parametrelerin sonucunda işlemler yapılarak geriye bilgi gönderen metotlardır.
Örnek Uygulama //Butonun Click Eventi private void btnBilgiGoster_Click(object sender, EventArgs e) { string bilgi = BilgiGoster(txtAd.Text, txtSoyad.Text, Convert.ToInt32(txtDogumYili.Text)); //Metodumuzu çağırdık. Bize string bir değer döndürdüğü için dönen değeri string bir değişkene aktardık. İstediği parametrelere SIRASIYLA ad, soyad ve doğum yılı bilgilerini gönderdik. MessageBox.Show(bilgi);//Dönen bilgiyi ekranda gösterdik. }
55 | S a y f a
//Metodumuz string BilgiGoster(string ad, string soyad, int dogumYili) { int yas = DateTime.Now.Year - Convert.ToInt32(dogumYili); //Şimdiki tarihten doğum yılını çıkarıyoruz ve yaşı elde ediyoruz. //String format ile bilgileri gösteriyoruz. return string.Format("Sayın {0} {1}, Yaşınız : {2}", ad, soyad.ToUpper(), yas); //ToUpper() metodu, yazının tamamını büyük harfe çevirir. }
1.18. STRING METOTLAR
String veri tipine özelleşmiş metotlardır. String ifadeler üzerinde değişiklik ve düzenleme yapmak için kullanılır. Çok sayıda string metot bulunmaktadır.
1.18.1.
Trim Metodu
Trim metodu string ifadede bulunan belli karakterleri baştan ve sonran silen metotdur. Trim metodu boşlukları temizleyebilir. Metot kullanımında dilersek kendi karakterlerimizi belirleyebiliriz. Verilen string ifadenin başında ve sonunda bulunan karakterleri temizlemek için kullanılır.
Trim Metodu private void btnTrim_Click(object sender, EventArgs e) { textBox1.Text = textBox1.Text.Trim();//Sağdaki ve soldaki tüm boslukları siler. textBox1.Text = textBox1.Text.Trim(' ', 'a', '!', '2', '\''); //Textboxda başta ve sonra bırakılan boşlukları temizler.Bu şekilde char dizisi tanımlanır ve bu yukarıda bulunan karakterlerin başta ve sonda olmasını engeller. Tek tırnak engellemek için başına \ ters slash kullanılarak yazılır. /' şeklinde tek tırnak engellenir. textBox1.Text = textBox1.Text.TrimStart();//Sadece Baştan karakterleri sil textBox1.Text = textBox1.Text.TrimEnd(); //sadece sondan karakterleri sil //Dönen değer string olduğu zamanlarda istediğimiz metotları tekrar tekrar kullanabiliriz. }
1.18.2.
Equals Metodu
Eşitlik sorgulaması yapar verilen iki string ifadenin birbirine eşit olup olmadığını kontrol eder. Eşitlik durumu sonucunda boolean değer döner. Boolean değeri kullanarak bu metodu karar yapılarımız içinde kullanabiliriz.
56 | S a y f a
Equals Metodu private void btnEquals_Click(object sender, EventArgs e) { bool esitmi = textBox1.Text.Equals(textBox2.Text, StringComparison.OrdinalIgnoreCase); //StringComparison.OrdinalIgnoreCase : metotu kücük büyük harf gözetmeksizin karşılaştırma //StringComparison.CurrentCultureIgnoreCase : hem kücük büyük harf gözetmeksizin kıyaslama hemde dil seceneğine göre kıyaslama MessageBox.Show(esitmi.ToString()); }
1.18.3.
SubString
String ifadede bulunan karakterlerden belirtilen index numarasından başlayarak string ifadenin sonuna kadar keser. Örneğin ‘BilgeAdam’ ifadesinde sadece ‘Adam’ ifadesinin SubString’i ni almak istersek kullanabiliriz.
SubString private void btnSubString_Click(object sender, EventArgs e) { textBox3.Text = textBox1.Text.Substring(2); //indexi 2 olan harften başlayarak sonuna kadar kes, yani 0 ve 1 index numaraları karakterleri sil 3. harften başlayarak sonuna kadar al.. textBox3.Text = textBox2.Text.Substring(2,4); //indexi 2 olan harften başlayarak 4 karakter al :) //Stringin boyutunu aşan bir substring işlemi yaparsak out of range hatası alırız. Bu hata string sınırlarını aşmak anlamına gelir. }
1.18.4.
Reserve
String ifadede ki karakter topluluğunu ters çevirmek için kullanılan string metotudur.
Yazılan kelime içerisinde belirttiğim karakteri arar. Örneğin BilgeAdam string ifadesinde ‘a’ harfini aramak istediğimde kullanabilirim. Burada dikkat edilmesi gereken nokta, ilk ‘a’ harfini bulup indexini döndürür. Diğer a harflerini aramaz. Eğer string ifade içerisinde aradığımız karakter bulunamazsa index değeri olarak -1 döner.
Index Of Metodu private void btnIndexOf_Click(object sender, EventArgs e) { textBox6.Text = textBox1.Text.IndexOf('a').ToString(); //String ifade içerisinde a harfini arar. textBox6.Text = textBox1.Text.IndexOf("alp").ToString(); //Şeklindede kullanılır. alp i arar ve ilk harf a nın indexini döndürür. textBox6.Text = textBox1.Text.IndexOf('a',1).ToString(); //1. indexten başlayarak bulmaya çalışır. Eğer hiç bir tanımlama vermezsek varsıylan olarak sıfır indexinden aramaya başlar. }
57 | S a y f a
1.18.6.
Remove
String ifade içeriside belirttiğimiz alanı kesebilir ve kestiğimiz alan dışında kalan kısmı elde edebiliriz.
Remove Metodu private void btnRemove_Click(object sender, EventArgs e) { textBox4.Text = textBox1.Text.Remove(2, 4); //2.index’den başla ve 4 karakter sil }
1.18.7.
Contains
Contains metodu, metot içerisinde verilen ifadenin, string ifade içerisinde olup olmadığını kontrol eden string metotdur. Boolean sonuç döndürür. Eğer string ifade verdiğimiz değeri içeriyorsa true, içermiyorsa false değeri döndürür.
String ifade içerisinde bulunan değerleri değiştirmek için kullanılır.
Replace Metodu private void btnReplace_Click(object sender, EventArgs e) { //İki kullanım vardır karakter ve ifade raplece yapmak. textBox7.Text = textBox1.Text.Replace('a', 'b');//ilk verdiğimiz char textbox 1 deki a ları textbox7 ye yazarken b yapar. Bu işlem karakter değiştirmek için. textBox7.Text = textBox1.Text.Replace("ayhan", "alp");//İfadeleri değiştirir. Textbox1 de ayhan yazdığı her yere alp yazar. }
1.18.9.
Split
String ifade içerisine verdiğimiz ayıraca göre string ifadeyi böler. Böldüğü ifadeyi bir diziye aktarır.
Split Metodu private void btnSplit_Click(object sender, EventArgs e) { //Split ayırmak string[] ayrimlar = textBox1.Text.Split(','); //içerisinde verdiğimiz ayıraca göre ayıracı gördüğü yerlerde stringi ayırır. örneğin textboxda alp,nazlı,duygu,ayhan,kadir dediğimde virgülleri ayırarak listbox a ekler. listBox1.Items.AddRange(ayrimlar); //Dizideki verileri listbox’a ekler. }
58 | S a y f a
1.18.10.
ToUpper
Verilen string ifade içerisindeki tüm harfleri büyük harf yapar.
ToUpper Metodu textBox7.Text = textBox1.Text.ToUpper();//Textbox da ki ifadeyi büyük harflerle yazar
1.18.11.
ToLower
Verilen string ifade içerisindeki tüm harfleri küçük harf yapar.
ToLower Metodu textBox7.Text = textBox1.Text.ToLower();//Textbox da ki ifadeyi küçük harflerle yazar
1.19. GUID
Bilgisayardaki çeşitli verilere bakarak rasgele bir alfanumeric karakter dizisi üretir. Oluşturulan bu karakter dizisi eşsizdir. Guid; resim ekleme, serial key üretme gibi işlemlerde kullanılabilir.
String metotları ve guid sınıfını kullanarak bir lisans key oluşturma programı yapalım. private void btnKeyOlustur_Click(object sender, EventArgs e) { string[] u = new string[4]; for (int i = 0; i < 10; i++) { string uzunkey = Guid.NewGuid().ToString(); uzunkey = uzunkey.Replace("-", "").ToUpper(); u[0] = uzunkey.Substring(0, 4); u[1] = uzunkey.Substring(5, 4); u[2] = uzunkey.Substring(9, 4); u[3] = uzunkey.Substring(13, 4); uzunkey = string.Format("{0}-{1}-{2}-{3}", u[0], u[1], u[2], u[3]); listBox1.Items.Add(uzunkey); } }
Yukarıdaki programı derlediğimizde, butona her tıkladığımızda “15FT-98AA-4FT9CC37” gibi bir çıktı sunacaktır.
1.20. MATH KÜTÜPHANESI
Hazır olarak onlarca matematiksel fonksiyonu bize sunan temel sınıftır. Yuvarlama islemleri, PI bilgisi, karekök, kuvvet vs...
59 | S a y f a
1.20.1.
PI Sayısı
Bir dairenin çevresinin çapına bölümü ile elde edilen sayıya verilen isimdir ve Math kütüphanesi bize bu değeri sunabilir
PI Sayısı private void btnPI_Click(object sender, EventArgs e) { this.Text = Math.PI.ToString(); }
1.20.2.
ABS
Mutlaka değeri ifade eden metottur, örneğin -45 sayısını iki düz çizgi içerisine alırsak dışarıya sayı +45 olarak çıkacaktır. |-45| = 45
Girilen iki değerlerin arasındaki en büyük değeri yakalar.
MAX private void btnMAX_Click(object sender, EventArgs e) { int maksimumdeger = Math.Max(45, 65); MessageBox.Show(maksimumdeger.ToString()); }
1.20.8.
MIN
Girilen iki değerlerin arasındaki en küçük değeri yakalar.
MIN private void btnMIN_Click(object sender, EventArgs e) { int minimumDeger = Math.Min(45, 65); MessageBox.Show(minimumDeger.ToString()); }
61 | S a y f a
1.20.9.
POW
Kuvvet alma işlemlerini gerçekleştirir. İlk parametrede hangi sayınin kuvveti alınacak, ikinci parametrede ise o sayının kaçıncı kuvveti alınacak diye sorar
Alıştırma: Form üzerinde yer alan 3 textbox ve Minumum Değer buttonunu kullanarak dışarıdan girilen 3 sayıdan en küçüğünü tek satırda gösteriniz
62 | S a y f a
OBJECT ORIENTED PROGRAMMING 2.1. Intro
Nesneye Yönelik Programlama, C Sharp tarafında tanımlı olmayan yapıları tanımlama imkanı sağlar. Örneğin, bir buton oluştururken Button btn = new Button(); şeklinde buton tanımlayabiliyoruz. Buton tanımlayabilmemizin nedeni, Button yapısının .net Framework ortamında tanımlı olmasından kaynaklanıyor.
Peki.. Biz kendi ihtiyaç duyduğumuz yapıları nasıl tanımlayacağız. .Net Framework bize çok gelişmiş ve kolay kullanılan bir yapı sunar. Kendi ihtiyaç duyduğumuz yapılar Framework ortamında tanımlı olmayacak. Button, Random vb sınıflar Framework ortamında tanımlıdır. Artık kendi sınıflarımızı oluşturabilmemiz gerekiyor.
Nesneye Yönelik Programlama, istediğimiz nesneyi bilgisayar ortamına taşıyabilir. Örnek vermek gerekirse Word programındaki boş sayfa.. Günlük hayattan bir A4 sayfayı bilgisayar ortamına taşımaktır.
Sağ tarafta bulanan resimdeki nesneyi (Tablet Bilgisayar) bilgisayar ortamına taşıyalım. Öncelikle bir class oluştururken sormamız gereken sorular vardır.
Oluşturmak istediğiniz nesne nedir? (Örnekde : Tablet) Bu sorunun cevabı bana oluşturacağım class’ın adını verir.
Bir nesnenin
özelliği vardır.
Bu sorunun cevapları oluşturacağımız class’da hangi özelliklerin olacağını bulmamızı kolaylaştırır.
Bir tabletin ağırlığı vardır. (double) Bir tabletin genişliği vardır. (double) Bir tabletin yüksekliği vardır. (double)
63 | S a y f a
Bir tabletin markası vardır. (string) Bir tabletin modeli vardır. (string) Bir tabletin mac adresi vardır. (string) Bir tabletin işlemci modeli vardır. (string) Bir tabletin ekran çözünürlüğü vardır. (string) Bir tabletin rengi vardır. (Color) Bir tabletin 3G vardır. (bool)
C Sharp tarafında tablete ait bilgileri tutmak için değişkenleri kullanmamız gerekir. Yukarıdaki özelliklerde, her bir özelliğin değişken tipi bulunmaktadır. Peki ben bu özellikleri bir arada tutmak istersem ne yapacağım? Bu özellikleri bir arada tutmam gerektiğinde dizi tanımlamam gerekir. Bir dizi tanımladığımda aynı çatı altında tutup, verilere daha kolay erişebilirim ama yukarıdaki örnekteki gibi farklı veri tipleri kullanmam gerektiğinde dizimin tipi object olmalıdır. Object dizisi ile veriyi tuttuğumda değeri dışarıya çıkartırken unboxing yapmam gerekir ayrıca verinin dizide hangi sırada olduğunuda bilmem gerekir. OOP kendi yapılarımızı tanımlayarak farklı tipleri tek çatı altında toplamamıza olanak sağlayabilir.
2.2. Class Object Mentality – Sınıf ve Nesne Mantığı
Nesneye Yönelik Programlamayı kullanabilmek için iki yapıyı çok iyi anlamamız gerekmektedir.
2.2.1. Class - Sınıf
Sınıflar (Class); nesne üretmek için kullandığımız kalıplardır. Bilgisayar ortamında tanımlayacağımız her bir class, bizim nesneler üretmemizi sağlar. Örneğin ben bir insan class’ı tanımlamak istediğimde oluşturacağım class tüm insanlarda bulunan özellikleri taşır. Saç rengi, göz rengi, boy, kilo ve diğer özellikler sınıf içerisinde tanımlanır ama içerisine değer atanmaz.
2.2.2. Object – Nesne Oluşturduğumuz sınıflardan nesneler üretebiliriz. Nesne üretmek için class’ımızın bir örneğini RAM üzerine çıkartmamız gerekir. Bu işleme instance alma adı verilir. Class üzerinde değer ataması yapılamaz, ama class’dan ürettiğimiz nesneler üzerinde değer atamaları gerçekleştirir.
Özetlemek gerekirse, Class genel bir tanımdır. Tüm nesnelerdeki özellikleri içerisinde barındırır ama nesne, class’dan üretileceği için sınıfda ki tüm özellikleri taşır ve içerisine değer alabilir.
2.2.3. Field and Property
Bizler verileri saklamak için değişkenleri kullanırız. Değişkenler RAM üzerinde verileri saklamak için kullanılan yapılardır. Bizler class’lar içerisinde bir değişken oluşturup bu
64 | S a y f a
değişkenlerde veri saklayabiliriz. Class içerisinde değişkenler yerine farklı bir yapı olan Field – Property yapısını kullanabiliriz. Field’lar class içerisinde oluşturulan, dışarıya kapalı değişkenlerdir. Field’lar içerisinde değer saklar. Field’lar dışarıya kapalı olduğundan field’a değer atanamaz ve field’da ki değeri okumak için Property kullanılır. Property field’a değer atamak ve field’da ki değeri okumak için kullanılan aracı bir yapıdır.
Peki neden değişken değilde, Field-Property yapısını kullanıyoruz. Biz bir değişken oluşturduğumuzda bu değişkene doğrudan erişim sağlarız. Ama Field – Property yapısı bizim Field’ı mıza doğrudan erişim sağlamamızı engeller ve Property içerisinde veri kontrollerini yapma imkanı tanır. Yani RAM üzerinde tuttuğumuz verinin kontrolünü Property içerisinde yapabiliriz.
Field ve Property ilişkisini bir örnekle açıklayalım.
Düşünün ki akşam güzel bir restoran’a yemeğe gidiyorsunuz. Arabanız ile restoranın önüne gittiniz arabanızı valeye teslim ettiniz. Vale arabayı otopark’a bıraktı ve siz restoran’dan ayrılırken arabanızı geri getirdi. İşte Field ve Property ilişkisini bu şekilde düşünebiliriz.
Field’ın görevi, içerisindeki verileri siz çağırana kadar güvenli bir şekilde saklamaktır. Property’nin görevi ise verinin güvenli bir şekilde field’a gitmesini ve ordan gelmesini sağlamaktır. Örneğimizde Property – Vale, Field ise Otoparktır. Örnekteki araba ise veridir. Vale arabanın güvenli bir şekilde otoparka gidip gelmesini sağlar. Otopark ise arabayı korur ve saklar.
65 | S a y f a
2.2.4. Encapsulation Encapsulation : Nesnenin üyelerine yapılan erişimin kontrol altına alınmasına ve bu kontrolün nesnenin kendisi tarafından yapılmasını sağlamaktır. Amaç fiedl'ları private yaparak bu alanlara dışarıdan erişimi önlemek ve get-set metotları ile kontrolü sağlamaktır.
Arka plan kodlarını gizleme : Oluşturulan class içerisinde kullanıcının işlemlerini daha kolay gerçekleştirmesi için bazı işlemleri birleştirerek (kapsüllenerek) tek işlem gibi gösterilir. Örneğin veritabanına bağlantı işleminde, biz sadece bağlantı değişkeninin Open() metodunu kullanmaktayız. Fakat class içerisinde kullanıcıdan aldığı parametreleri kullanarak bağlantıyı gerçekleştirmek için birçok metot bulunmaktadır. Bu metodları kullanıcıya gösterip bağlantıyı saglayabilmek için bunlari su sekilde birlestirin demek yerine bu islem sinif içerisinde yapilmis ve kullanıcının kolaylikla kullanabilmesi için Open() metodu oluşturulmuştur.
Değişkenlere tam erişimi engelleme : Class içerisinde olusturduğumuz global değişkenlere dışarıdan erişmek için public olarak tanimlama yapmaktayiz. Fakat bazen bu degışkenlerin değerlerini değiştirmek istemeyebiliriz. Fakat kullanmamız da gerekebilir. Bu durumda değişkenimizi kapsüllememiz gerekmektedir. Yani, bu değişkeni private olarak tanımlamak ve bir read-only property ile bu değişkenin yazma iznini ortadan kaldırmamız gerekmektedir.
Class class Urun { int _id; //id bilgisine dışarıdan erişimi engelledik. public int Id //_id field'ına dışarıdan erişilemeyecek fakat field'tan türetilen property dışarıyla haberleşip field'tan değer alıp dışarıya atacak, dışarıdaki değeri alıp field'a ulaştıracaktır. { get { return _id; } // field'taki değeri dış dünyaya gönderir set { _id = value; } // dışarıdan alınan değeri field'a basar } string _ad; public string Ad { get { return _ad; } set { _ad = value; } } double _fiyat;
66 | S a y f a
public double Fiyat { get { return _fiyat; } set { if (value > 0) //dış dünyadan alınan değer istediğim değere uygun ise değeri al ve field'a gönder _fiyat = value; else //dış dünyadan alınan değer istediğim değere uygun değilse, uyarı ver ve field'a herhangi bir değer set etme! System.Windows.Forms.MessageBox.Show("Fiyat negatif olamaz."); } } }
Form:
2.3. Methods in Class
Classlar sadece içerisinde özellikleri taşımaz aynı zamanda metodlarda barındırabilir. Bir class’ın özelliklerini belirlemek için “Bir class’ın …….. ’sı vardır” sorusunu kullanıyorduk. Metotlar için ise, “Bir class …….. yapabilir mi sorusunu sorabiliriz.” Class içerisinde kullandığımız metotlar, hazırladığımız sınıf ile ilgili işlemleri yapar.
2.4. Constructor – Yapıcı Metot
Şu ana kadar instance alma işleminde Button btn = new Button(); şeklinde bir kod kullandık. Şimdi instance alma işlemini detaylı inceleyip Constructor’ın ne olduğundan bahsedelim.
67 | S a y f a
Constructor, yapılandırıcı metot olarak kullanılır. Bir class’dan instance alındığında ilk tetiklenecek olan metodtur. Geriye dönüş tipi yoktur. Yeni bir form oluşturduğumuzda aşağıda ki yapı oluşacaktır.
Form 1 public partial class Form1 : Form { //Constructor //Yapılandırıcı metot geriye dönüş tipi yoktur. public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { } }
Yapılandırıcı metot class’dan instance alma işlemi sırasında tetiklenir. Bir class oluşturduğumuzda constructor metot göremeyiz ama bu yapılandırıcı metodun olmadığı anlamına gelmez. Eğer bir class’da instance işlemi sırasında herhangi bir işlem yapılmayacaksa constructor’ı yazmak zorunda değiliz.
Instance alma işlemi sırasında kullanıcıdan bilgi almak istendiğinde kullanılır. Kullancı class’dan instance almaya çalıştığında gerekli şartları sağlayamıyorsa instance alamaz.
2.5. This Keyword
This; ‘bu’ anlamına gelmektedir. Programlama dilindeki anlamı üzerinde çalıştığımız sayfa olarak tanımlanabilir. Örneğin Form1 class’ın da Runtime’da yeni bir kontrol oluşturup kontrolü forma eklemek istediğimizde
this.Controls.Add(kontrolAdi);
Komutunu kullanırız. Burada kullandığımız this üzerinde çalıştığımız class’ı temsil etmektedir. This yazarak çalıştığımız sayfa üzerindeki tüm property ve metotlara erişebiliriz.
68 | S a y f a
2.6. Access Modifiers (Erişim Belirteçleri)
Erişim belirteçi anlamına gelen Access Modifiers, classlar, metotlar ve değişken gibi yapıların erişim durumlarını belirler. Classlar hariç tanımlanan yapıların varsayılan Erişim belirteci private’dır. Private yapının dışarıya açılmayacağını ve sadece this keyword’ünde kullanılacağını belirtir. Erişim belirteçleri ile ilgili detaylı bilgiyi aşağıdaki tabloda bulabilirsiniz.
Private : Bu erişim belirteci ile tanımlanan öğeler sadece tanımlandıkları sınıf (class) ya da yapı (struct) içinde erişilebilirler. En kısıtlayıcı belirteçtir. Public : Kısıtlama yoktur. Public olarak tanımlanan öğeler aynı projeden ya da kendisini referans olarak gösteren diğer projeler tarafından erişilebilirler. Protected : Bu şekilde tanımlanan öğeler, tanımlandıkları sınıf (class) ya da yapı (struct) veya bu sınıflardan türetilmiş diğer sınıflar içerisinden erişilebilirler. Internal : Internal tanımlanan classlar bulundukları proje içerisinde her yerden erişilebilir ancak başka bir proje tarafından kullanılamazlar. Protected Internal : Bu belirteç uygulanan öğenin Protected ya da Internal olduğunu vurgular. Yani Protected Internal bir öğe aynı proje içindeki tüm sınıflardan erişilebileceği gibi, bulunduğu sınıftan türetilmiş diğer sınıflardan da erişilebilir.
2.7. Static Class ve Static Members
Static olarak işaretlenen bir class veya classın içerdiği bir elemanı proje çalıştırıldığında doğrudan RAM bellek üzerine çıkartılır. Static olarak işaretlenmiş bir yapıyı kullanmak için instance alma işlemeni yapmak zorunda kalmayız. Instance alma işlemi kullanılacak yapının RAM bellek üzerine çıkartılmasını sağlar. Fakat static olarak işaretlenmiş bir yapı proje çalıştığında zaten RAM bellek üzerine çıkartılacağı için instance alma işlemine gerek kalmamaktadır.
Static olarak işaretlenmiş ve .net Framework ortamında tanımlı olan classlarda vardır. Bu classlara örnek vermek gerekirse;
MessageBox Sınıfı Math Sınıfı Guid Sınıfı
2.8. Reference Type ve Value Type
CSharp’ta tipler referans type ve value type olmak üzere ikiye ayrılırlar.
2.8.1. Value Type (Değer Tipi)
Value Type değer tipleri, RAM üzerinde ki STACK alanında yaşarlar. STACK alanında açılan yerde doğrudan değişken içerisindeki bilgi tutulur. Int,bool, double, float vb. değerler STACK alanında saklanmaktadır. Değer tiplerinin belli aralıkları bulunmaktadır.
69 | S a y f a
int sayi = 5;
İfadesinde, HEAP bölümünde sayi isminde bir alan açıyoruz. Bu alan içerisinde 5 sayısını tutuyoruz. Değer tiplerinde, içeride bilginin kendisi tutulur.
Aşağıdaki resimde değer tiplerini ve sahip oldukları değer aralıklarını görmektesiniz.
2.8.2. Reference Type (Referans Tipi) Referans Type ise değişken RAM’in HEAP alanında yaşar. String, object veri tipleri ve classlar RAM’in Referans Tipleri arasındadır. Referans tiplerinin değerleri HEAP alanında tutulurken, STACK alanında, değeri işaret eden bir adres bulunur. Biz veriyi okumak istediğimizde, STACK üzerinde ki referans adresinden, HEAP’de verinin tutulduğu alana giderek veriye ulaşabiliriz.
70 | S a y f a
2.9. Inheritance
Inheritance, biyolojiden programlama diline geçen bir terimdir. Canlılarda bulunan kalıtım özelliği anlamına gelir. Object Oriented Programming gerçek hayattaki yapıları bilgisayar ortamına taşımamızı sağlar. OOP yapısı biyolojide bulunan bir çok terimden faydalanır.
Biyolojide ki kalıtım özelliği, canlılardaki özelliklerin yeni canlılara aktarılmasıdır. Aynı yöntemle bizde oluşturduğumuz classlar arasında bir kalıtım özelliği sağlayabiliriz. Bu kalıtım özelliğini kullanarak özellik ve yetenekleri Base class olarak tabir edilen ana class’dan üretilmiş olan classlara miras bırakabiliriz. Inheritance bize ne sağlar?
Geliştirilebilir bir yapı Kontrol edilebilir classlar Tek elden yönetim
En sade şekli ile: inheritance sayesinde bir sınıfın metodlarını ve propertylerini kullanan başka sınıflar türetilebilmesini sağlar diyebiliriz.
Aşağıdaki örnekte bir şirketin departmanlarını oluşturalım. Firmamızda bulunan departmanlar
Muhasebe Departmanı İnsan Kaynakları Departmanı Teknik Servis Departmanı
Yukarıda bulunan departmanları OOP ile oluşturalım. Buradaki önemli nokta bu departmanlarda çalışan her bir kişi bir insandır.
Muhasebe.cs class Muhasebe { //Her Insana Ait Özellikler public string AdSoyad { get; set; } public DateTime DogumTarihi { get; set; } public bool ErkekMi { get; set; } public double Kilo { get; set; } public double Boy { get; set; } public bool EhliyetiVarMi { get; set; } public bool SaglikSorunuVarmi { get; set; } public decimal AldigiUcret { get; set; } //Muhasebe Departmanına Ait Özellikler public bool MaasBilgileriniGorebilir { get; set; } public bool MaasBilgileriniDegistirebilir { get; set; } }
71 | S a y f a
InsanKaynaklari.cs class InsanKaynaklari { //Her Insana Ait Özellikler public string AdSoyad { get; set; } public DateTime DogumTarihi { get; set; } public bool ErkekMi { get; set; } public double Kilo { get; set; } public double Boy { get; set; } public bool EhliyetiVarMi { get; set; } public bool SaglikSorunuVarmi { get; set; } public decimal AldigiUcret { get; set; } //İnsan Kaynakları Departmanına Ait Özellikler public bool IseAlabilir { get; set; } public bool UcretBelirleyebilir { get; set; } public bool CalismaSaatiBelirleyebilir { get; set; } }
TeknikServis.cs class TeknikServis { //Her Insana Ait Özellikler public string AdSoyad { get; set; } public DateTime DogumTarihi { get; set; } public bool ErkekMi { get; set; } public double Kilo { get; set; } public double Boy { get; set; } public bool EhliyetiVarMi { get; set; } public bool SaglikSorunuVarmi { get; set; } public decimal AldigiUcret { get; set; } //Teknik Servis Departmanına Ait Özellikler public bool AgKurabilir { get; set; } public bool TeknikDestekVerebilir { get; set; } public bool BilgisayarAlabilir { get; set; } }
Yukarıdaki classlarda farklı departmanlara ait bilgileri görmektesiniz. Bu departmanlarda tekrarlayan bilgiler dikkatinizi çekmiştir. Insana ait özellikler tüm departmanlarda aynı olmalıdır. Yukarıdaki yapıda bir OOP yapısı oluşturduğumuzda geliştirilebilirlik ve yönetilebilirlik zor olmaktadır. Firmaya ait onlarca departman olduğunu düşündüğümüzde Insan’a ait yeni bir özellik eklediğimizde veya bir özelliği kaldırdığımızda tüm classlar içerisinde bu değişikliği yapmamız gerekmektedir. Bunun dışında insana ait bilgileri tüm classlarda tanımlamamız gerekmektedir bu da bizim için kod tekrarı demektir.
Yukarıdaki yapı yerine, bir “Insan” classı oluştursak ve bu class’ın özelliklerini başka classlara kalıtım olarak bırakmayı denesek yapı ne kadar esnek olur?
72 | S a y f a
Hadi Deneyelim..
Öncelikle insana ait bir class oluşturup tüm departmanlarda bulunan insanların özelliklerini bu class içerisine ekliyoruz.
Insan.cs class Insan { //Her Insana Ait Özellikler public string AdSoyad { get; set; } public DateTime DogumTarihi { get; set; } public bool ErkekMi { get; set; } public double Kilo { get; set; } public double Boy { get; set; } public bool EhliyetiVarMi { get; set; } public bool SaglikSorunuVarmi { get; set; } public decimal AldigiUcret { get; set; } }
Yukarıda bir insana ait tüm özellikleri tanımladık. Peki departmanların özelliklerini nasıl tanımlayacağız? Departman özelliklerinide her departmana göre class oluşturarak tanımlayalım.
Muhasebe.cs class Muhasebe { //Muhasebe Departmanına Ait Özellikler public bool MaasBilgileriniGorebilir { get; set; } public bool MaasBilgileriniDegistirebilir { get; set; } }
InsanKaynaklari.cs class InsanKaynaklari { //İnsan Kaynakları Departmanına Ait Özellikler public bool IseAlabilir { get; set; } public bool UcretBelirleyebilir { get; set; } public bool CalismaSaatiBelirleyebilir { get; set; } }
TeknikServis.cs //Teknik Servis Departmanına Ait Özellikler public bool AgKurabilir { get; set; } public bool TeknikDestekVerebilir { get; set; } public bool BilgisayarAlabilir { get; set; }
73 | S a y f a
Yukarıda gördüğünüz gibi tüm departman bilgilerini kendilerine ait classlarda tanımladık ama insana ait özellikler farklı bir class olan “Insan” classında.. Şimdi “Insan” classından departman classlarına kalıtım vererek insana ait özelliklerin tüm departmanlara kolay bir şekilde miras bırakabiliriz. Kalıtım verme özelliği class adının yanına ‘:’ ‘den sonra classın adını yazarak verilir. ‘:’ dan sonra yazılan class “Base Class” olarak geçer. Bir classın yanlızca bir Base Classı olabilir. Aşağıdaki kod bloklarında Insan classını nasıl kalıtım olarak bırakabileceğimizi görelim.
Muhasebe.cs class Muhasebe : Insan //: dan sonra Insan classından miras alındığını belirtiyoruz. { //Muhasebe Departmanına Ait Özellikler public bool MaasBilgileriniGorebilir { get; set; } public bool MaasBilgileriniDegistirebilir { get; set; } }
InsanKaynaklari.cs class InsanKaynaklari : Insan //: dan sonra Insan classından miras alındığını belirtiyoruz. { //İnsan Kaynakları Departmanına Ait Özellikler public bool IseAlabilir { get; set; } public bool UcretBelirleyebilir { get; set; } public bool CalismaSaatiBelirleyebilir { get; set; } }
TeknikServis.cs class TeknikServis : Insan //: dan sonra Insan classından miras alındığını belirtiyoruz. { //Teknik Servis Departmanına Ait Özellikler public bool AgKurabilir { get; set; } public bool TeknikDestekVerebilir { get; set; } public bool BilgisayarAlabilir { get; set; } }
Yukarıdaki kod satırlarında class adından sonra yazdığımız “: Insan” tanımlaması, classımızın Base Class tanımlamasıdır. Yani propertyleri, metotları vb. diğer yapıları Insan classından miras alabileceği anlamına gelir. Miras alınan class, Base classın tüm özelliklerini kullanabilir.
Tekrar ve tekrar belirtmek gerekir ki : Bir class’ın yanlızca bir “Base Class”ı olabilir. Yani bir class sadece bir classdan miras alabilir.
Classlar arası miras verme işlemini ebeveyn – çocuk ilişkisine benzetebiliriz. Bir çocuğun, biyolojik olarak bir anne - baba ebeveyn ikilisi vardır. Bir çocuğun biyolojik olarak birden fazla anne ve babası olamaz.
74 | S a y f a
Ama dikkat etmemiz gereken nokta, bir ebeveyn ikilisinin birden fazla çocuğu olabilir. İşte bu yapı kalıtım (Inheritance) yapısıdır.
Bir class’ın, bir base classı olabilir. (Bir çocuğun bir anne-babası olabilir.) Bir Base Class birden fazla classa kalıtım verebilir. (Bir anne-babanın birden fazla çocuğu olabilir.)
2.9.1. Birden Fazla Classdan Miras Almamız Gerektiğinde Ne Yapmamız Gerekir?
Aşağıdaki class örneğide; bir timsahın bilimsel sınıflandırılması yapılmaktadır. Timsah bir hayvandır. Aynı zamanda timsah bir sürüngendir. Bu örnekten yola çıkarak; Timsah ve Bukalemun’un kalıtım özelliklerini hazırlayalım.
Dikkat etmemiz gereken nokta, C Sharp dilinde Multi-Inheritance özelliği bulunmamaktadır. Yani yukarıda da bahsettiğimiz gibi bir classın birden fazla Base Classı olamaz.
Hayvan.cs class Hayvan { //Tüm hayvanların ortak özellikleri public double Boyu { get; set; } public double Kilosu { get; set; } public Color Rengi { get; set; } public DateTime DogumTarihi { get; set; } }
Surungen.cs //Tüm sürüngenler bir hayvandır. Bu sebeple sürüngen, hayvandaki özellikleri miras alır. class Surungen : Hayvan { //Sürüngenlere ait ortak özellikler public bool AyaklariVarMi { get; set; } public bool DerisiZirhliMi { get; set; } }
Timsah.cs //Timsah bir sürüngendir. Sürüngen' hayvan classından miras aldığı için, hem hayvanın hem sürüngenin özelliklerini miras almalıdır. class Timsah : Surungen //Sürüngen classı, hayvan classından miras aldığı için Hayvan classı sadece sürüngen classından miras almalıdır. {
75 | S a y f a
//Timsaha ait özellikler public int DisSayisi { get; set; } }
Bukalemun.cs //Bukalemun bir sürüngendir. Sürüngen' hayvan classından miras aldığı için, hem hayvanın hem sürüngenin özelliklerini miras almalıdır. class Bukalemun { //Bukalemuna ait özellikler public bool RenkDegistirebilirMi { get; set; } }
Yilan.cs //Yilan bir sürüngendir. Sürüngen' hayvan classından miras aldığı için, hem hayvanın hem sürüngenin özelliklerini miras almalıdır. class Yilan { //Yilana ait özellikler public bool DeriDegistirebilirMi { get; set; } public bool ZehirliMi { get; set; } }
2.10. Abstract Class
Abstract Class, ortak özellikli Class’lara Base Class olma görevini üstlenir. Abstract Class’lar, diğer sınıflara base Class olmak için yazılır. Bu nedenle Abstract Class’dan nesne türetilemez.
Abstract öğelerin amacı, kendisinden kalıtım alan sınıflarda bir takım özelliklerin kullanılmasını zorunlu kılmaktır.. Eğer bir abstract içerisinde abstract bir öğe tanımladıysanız o öğeye bir kod gövdesi belirtemezsiniz. Değişkenleri abstract olarak işaretleyemeyiz.
Bir abstract öğeyi bir sınıfa yerleştirebilmek için o sınıfın mutlaka abstract olmasi gerekmektedir...
2.11. Polymorphism
Inheritance gibi biyolojiden, programlama diline geçmiş bir terimdir. Canlılarda ki çok biçimliliktir. Bir metodun farklı sınıflar için farklı etkiler oluşturmasını sağlayan bir yöntemdir.
Bu iki işlem için oluşturulacak metotlar aynı işi, farklı yöntemler ile yapmaktadır. Bir tanesi bizim veritabanımıza müşteriden alınan siparişi kayıt ederken, diğer metot stoğumuz azaldığında tedarikçiye bilgi göndererek ürün siparişi verir.
Örneğimizde bir sipariş classımız bulunmaktadır. Sipariş işlemini hem müşteri, hem de firma yapabilir. Biz sipariş classımızda oluşturduğumuz SiparisVer() metodunu farklı iki classda kullanacağız.
Siparis.cs, Musteri.cs, Firma.cs isimleriyle üç class oluşturuyoruz. Sırasıyla classlarımızın içeriğini aşağıdaki gibi düzenleyin.
Siparis.cs public class Siparis { public virtual string SiparisVer() { return "Sipariş verme işlemi için SiparisVer metodunu tanımlamanız gerekmektedir."; } }
Musteri.cs public class Musteri : Siparis //Siparis Classından SiparisVer metodunu miras alıyoruz. { public override string SiparisVer() { return string.Format("Müşteri, firmamıza başarıyla sipariş verdi."); } }
Firma.cs public class Firma : Siparis //Siparis Classından SiparisVer metodunu miras alıyoruz. { //Firmanın Müşteriye Sipariş Vermesi public override string SiparisVer() { return string.Format("Firma, tedarikçiye başarıyla sipariş verdi."); } }
Miras verme işleminden sonra, Siparis classı içerisinde tanımlanan SiparisVer() metodu virtual olarak işaretlenir. Virtual olarak işaretlenen metotlar miras aldığı classlarda ezilebilir olur. Biz SiparisVer() metodunu ezerek istediğimiz işlemleri yapabiliriz.
77 | S a y f a
Yukarıdaki kodu çalıştırdığımızda farklı classlar için SiparisVer() çağırdığımızda çağırdığımız class içerisindeki metot çalışacaktır.
metodunu
ToString() metodu virtual olarak işaretlenmiştir.
2.12. Delegates ve Eventler
Bir olay gerçekleştiğinde birden fazla fonksiyonu çağırmak istediğinizi düşünelim. Örneğin kullanıcı bir düğmeye tıkladığında birden fazla method'un otomatik olarak çağrılmasını istiyorsunuz. Bunun için delegate kullanabilirsiniz.
2.12.1.
Deletegate Oluştururken izlenecek adımlar
1.Tanımlama-Declare 2.Örneklenme-Instance 3. Çağırma - Invoke Delegateler başka fonksiyonlara aracılık eden özel fonksiyonlardır.
Delegate olarak bir method tanımlanır. Bu method aslında temsilcidir. Bir olay olduğunda siz delegate method'unu çağrırsınız. Delegate method'una kendisini ekleyen method'lar otamatik olarak çağrılırlar. Aşağıda basit bir delegate methodu yaratıyoruz.
Delegate Örneği class Program { //Delegateler namespace altında tanımlanabilir. public delegate int MyDelegate(int Sayi1, int Sayi2); //Delegate içerisinde kullanılacak metot. static int Carp(int sayi1, int sayi2) { return sayi1 * sayi2; } //Console Uygulaması static void Main(string[] args) { //Delegate' in instance' ını oluşturalım. MyDelegate delege = new MyDelegate(Carp); //Deleagate Çağıralım ( invoke)
78 | S a y f a
int iCarpim = delege(3, 4); //Invocation Console.WriteLine("Çarpım Sonucu :{0}", iCarpim); Console.ReadLine(); } }
2.12.2. Eventler Event, belirli bir olayda veya belirli bir zamanda meydana gelen yada meydana gelmesini istediğimiz işlemleri tasarlayacağımız olayların bütünüdür. Örneğin bir düğmenin tıklanması bir event oluşturur. Olay güdümlü programlama dillerinin temelini oluştururlar. Eventler, bir kontrolü kullanmamız için gereken zaman kavramlarıdır. Butonun tıklanması, formun yüklenmesi gibi zamanlarda yapılacak işlemleri yönetirler.
Programı zaman aralıklarına göre yönetebiliriz, kullanıcının işlem yaptığı zamanları programlayarak işlemlerimizi yapabiliriz.
C Sharp’da en çok kullanılan eventler ve açıklamaları aşağıdadır.
Kontrol
Event
Açıklama
Tüm Kontroller Tüm Kontroller Tüm Kontroller
Click DoubleClick MouseClick
Tüm Kontroller
MouseDoubleClick
Tüm Kontroller
MouseMove
Tüm Kontroller Tüm Kontroller Tüm Kontroller
MouseEnter MouseLeave MouseDown
ComboBox, Listbox, ListView
SelectedIndexChanged
Kullanıcının kontrole tıkladığı zaman aralığında tetiklenen eventtir. Kullanıcının kontrole çift tıklığı zaman aralığında tetiklenen eventtir. Kullanıcının kontrole mouse ile tıkladığı zaman aralığında tetiklenen eventtir. Kullanıcının kontrole mouse ile çift tıkladığı zaman aralığında tetiklenen eventtir. Kullanıcının ilgili kontrol üzerinde fare imlecini hareket ettirdiğinde tetiklenen eventtir. Kullanıcının ilgili kontrol üzerine mouse ile geldiğinde tetiklenen eventtir. Kullanıcının kontrol üzerinden ayrılındığında tetiklenen eventtir. Mouse tuşuna basıldığında tetiklenir. Click olayından önce çalışan bir olaydır. Seçili index değiştiğinde tetiklenen eventtir.
2.13. Interface
Interfacelere türkçe karşılığı olarak arayüz dememiz yanlış olur, Interfaceler C Sharp tarafında yetenek olarak tanımlanabilir.
Interfaceler, class veya struct gibi türler için oluşturulmuş modellerdir. Interfaceler bir sınıfın temelde hangi üyelerden oluşacağını belirleyen şablon yapılarıdır. Bu sayede oluşturulacak sınıflara öncülük edilir ve içermeleri gereken üyelerin ne olacağının standardı belirlenir. Kullanılması zorunlu olan metotlar belirlenir fakat metot içerikleri
79 | S a y f a
doldurulmaz. Simülasyon metot olarak hazırlandıktan sonra, yetenek olarak kazandırıldıkları Class’a bu metotlar implament edilir. Metot içerikleri class içerisinde doldurulur.
Genelde büyük ölçekli projelerde önem kazanmaktadırlar. Interface yapılarını interface anahtar sözcüğü ile tanımlarız. Ara birimleri sınıflar üzerinde uygulamak için ise “:” işareti kullanılır ve standart olarak interface isimleri “I” harfi ile başlar, tabi bu bir zorunluluk değildir. Fakat bu şekilde kullanılması standart olarak kabul edilir. Burada ki ‘I’ harfi Interface’in ilk harfidir.
Inheritance yapısında bir class’ın bir base class’ı bulunmaktaydı. Bir class’a birden fazla classdan kalıtım bırakmak istediğimizde hiyerarşik bir yapı oluşturuyorduk. Interfacelerde bu durum geçerli değildir. Bir class’a birden fazla interface’den yetenek kazandırabiliriz.
Bir insan classımızın olduğunu düşünelim. İnsan yapısından türeyen garson, müşteri ve patron classları bulunmaktadır. Bu classların (garson.cs, musteri.cs, patron.cs) temel yapıları aynıdır. Ama insana ait yetenekler dışında kendilerine ait yetenekleride bulunur. Böyle bir yapıda patrona ve müşteriye servis yapabilme yeteneğini vermememiz gerekir. Restoran örneği çerçevesinde bulunan yeteneklerin listesini çıkaralım
Garsonun servis yapma yeteneği vardır. Ama patronun ve müşterinin bu yeteneklere sahip olmaması gerekir. Patronun ve müşterinin ödeme Yapma yeteneği vardır. Ama garsonun ödeme yapma yeteneği olmamalı.
Yukarıda bahsettiğimiz Garson, Müşteri ve Patron classlarının hepsi insan classından türemiş olacaktır. Biz ParaOde(), ServisYap() gibi metotları insan classında mı tanımlamalıyız?
Yukarıdada belirttiğimiz gibi ParaOde metodu birden fazla yerde kullanılacak. Peki ben metodumu her class için ayrı ayrı tanımlamak zorundamıyım?
ParaOde yeteneğini Insan classında tanımlarsak, garson’a da ParaOde yeteneğini kazandırmış oluruz.
80 | S a y f a
Biz yetenek diye bir class tanımlayıp, o classı başka bir class’a yetenek olarak miras bırakamayız. Bunun sebebi yukarıdaki yapıların hepsinin Insan classından türemiş olmasıdır. Inheritance’da bahsettiğimiz kuralı hatırlayalım. Bir Class’ın, Birden fazla Base Class’ı olamaz!
İşte bu durumda interface devreye giriyor.
Bir örnek ile inceleyelim.. Aşağıda bulunan kuş classını oluşturalım. Kuş classını base class olarak kullanarak, Martı, Karga, Tavuk ve Penguen classlarımızıda oluşturalım.
Kus.cs public class Kus { public decimal GagaBoyu { get; set; } public Color TuyRengi { get; set; } }
Karga.cs public class Karga : Kus { }
Marti.cs public class Marti : Kus { }
Penguen.cs public class Penguen : Kus { }
Tavuk.cs public class Tavuk : Kus { }
Yukarıda görüldüğü gibi tüm classlar Kus.cs classından miras aldı. Peki Kus classından üretilen tüm classları inceleyelim.
81 | S a y f a
Yukarda tanımladığımız kuşların (martı, penguen, karga, tavuk) hepsi uçabiliyormu? Yukarda tanımladığımız kuşların (martı, penguen, karga, tavuk) hepsi yüzebiliyormu? Yukarda tanımladığımız kuşların (martı, penguen, karga, tavuk) hepsi yumurtlayabiliyormu?
Şimdi ben bu işlemleri yönetmek için bir uçma yeteneği tanımlayacağım. Interface’ler standart olarak isimlerinin başlarına ‘I’ karakteri eklenerek tanımlanır. ‘I’ -> Interface’i temsil eder.
Add > New sekmesini kullanarak interface dosyasını seçiyoruz ve ismini IUcabilir olarak belirleyip oluşturuyoruz. Dosyayı oluşturduğumuzda aşağıdaki kodları bize oluşturacaktır.
IUcabilir.cs public interface IUcabilir { //Aşağıda geriye dönüş tipi int olan Uc isimli bir metot tanımlıyoruz. int Uc(); }
Interface’ler içerisinde metodun gövdesi doldurulmaz ve erişim belirteçi belirlenmez. Sadece metod tanımlaması yapılır. Biz interface içerisinde sadece yapımızı tanımlıyoruz.
Yukarıda oluşturduğumuz interface’i uçabilen kuşlara yetenek olarak kazandırabiliriz. Bu işleme Interface Implament etmek denir. Oluşturduğumuz yeteneği classımıza kazandırmak için aşağıdaki kodları inceleyiniz.
Karga.cs //Karga kuştan miras aldığı için başka bir classdan miras alamaz. //Ama bir class a sınırsız yetenek kazandırabiliriz. //Bir class'a yetenek kazandırmak için class'dan sonra ',' karakteriyle yeteneklerimizi ekleriz. public class Karga : Kus, IUcabilir //Yeteneğimizi ekledik. { }
Yukarıdaki işlemi tamamladıktan sonra projeyi derlediğimizde aşağıdaki hata ile karşılaşacağız.
82 | S a y f a
“IUcabilir’de bulunan Uc metodu, karga classında bulunmuyor” diye bir hata verdi. Bu hatanın sebebi henüz oluşturduğumuz yeteneği, classımıza kazandırmadığımızdan dolayı çıkıyor.
Yeteneği class’a kazandırmak için virgülden sonra yazdığımız IUcabilir tanımlamasının üzerine tıklıyoruz ve CTRL+. (Kontrol + nokta) tuş kombinasyonunu kullanıyoruz. Implament Interface ‘IUcabilir’ seçeneğine tıklıyoruz ve classımızın içerisinde metodun gövdesiyle birlikte oluştuğunu görebiliriz.
Karga.cs public class Karga : Kus, IUcabilir //Yeteneğimizi ekledik. { public int Uc() { throw new NotImplementedException(); } }
Dosyamızı Implament ettiğimizde metodumuzu gövdesi doldurulmak üzere hazırladı. Şimdi yapmamız gereken tek şey metodumuzun gövdesini doldurmak Metod içerisinde karganın uçuş mesafesini döndürüyorum.
Karga.cs public class Karga : Kus, IUcabilir //Yeteneğimizi ekledik. { public int Uc() { return 50; //Karga 50 birim yüksekten uçabilir } }
Peki martı uçabilirmi? -Evet.. Yukarıda yaptığımız işlemi yapalım. IUcabilir interface’ini yetenek olarak ekleyip, dosyamızı implament edelim. Artık martı classımızda Uçma yeteneği kazanmış olacaktır.
83 | S a y f a
Karga.cs public class Marti : Kus, IUcabilir //Yeteneğimizi ekledik. { public int Uc() { return 100; //Martı 100 birim yüksekten uçabilir } }
Penguen ve Tavuk Uçabilir Mi? –Hayır.. O zaman IUcabilir interface’ini penguen ve tavuk classlarına yetenek olarak kazandırmıyoruz. Yani uçabilenler iki tane ama hepsi kuştur.
Şimdi bir form görünümü oluşturuyorum ve forma eklediğim button eventinin içerisine yukarıda oluşturduğum classların hepsinden instance alarak listbox’a ekliyoruz. Daha sonra projeyi çalıştırıp doldur butonuna tıklıyoruz.
Forma eklediğimiz butonun Click Eventi private void btnDoldur_Click(object sender, EventArgs e) { //Kuş classından ürettiğimiz tüm classlardan instance alıyoruz. Marti m = new Marti(); Karga k = new Karga(); Tavuk t = new Tavuk(); Penguen p = new Penguen(); //Instance aldığımız nesneleri listbox'a ekliyoruz. lstClasslar.Items.Add(m); lstClasslar.Items.Add(k); lstClasslar.Items.Add(t); lstClasslar.Items.Add(p); }
84 | S a y f a
Şimdi bir yetenek daha belirleyelim. Yukarıda oluşturduğumuz hayvan classlarından uçabilenler dışında yüzebilenlerde var. Şimdi ‘IYuzebilir’ isminde bir interface daha tanımlıyoruz.
IYuzebilir.cs public interface IYuzebilir { //Aşağıda geriye dönüş tipi int olan Uc isimli bir metot tanımlıyoruz. int Yuz(); }
Yüzme yeteneğine sahip olan classlar martı ve penguen classlarıdır. İlk olarak yüzme yeteneğini Penguen’e kazandırıyorum. Martı ve Kargaya yetenek kazandırdığımız gibi penguen classına da yetenek kazandırıyoruz.
Penguen.cs public class Penguen : Kus, IYuzebilir { //Interface içeriğini implament etmeyi unutmuyoruz. public int Yuz() { return -50; //Marti -200 birimden yüzebilir } }
Güzel, Penguen classına yüzme yeteneğini kazandırdık. Martıda yüzebileceği için, martı classınada yüzme yeteneği kazandırıyoruz. Daha önceden martı classına uçma yeteneği kazandırmıştık. İkinci yetenek olarak yüzme yeteneğinide kazandırıyoruz.
Marti.cs public class Marti : Kus, IUcabilir, IYuzebilir //Yüzme yeteneğimizi , den sonra ekliyoruz. { public int Uc() { return 100; //Marti 100 birim yüksekten uçabilir } public int Yuz() { return -50; //Marti -50 birimden yüzebilir } }
85 | S a y f a
Yüzme yeteneğinide implament ettikten sonra yukarıda gördüğünüz gibi iki Interface’e ait metodlar marti classına eklendi. Tek yapmamız gereken metot gövdelerini doldurmaktır.
Microsoft SQL SERVER
3.1. MS SQL Kavramları & Terimleri
Microsoft SQL Server’ın ne olduğuna geçmeden önce veritabanı kavramını açıklayalım;
3.1.1. Veri Tabanı (Database) Nedir ?
Veritabanı, düzenli veriler topluluğudur. Birbirleri ile ilişkili verilerin tekrarına yer vermeden çok amaçlı olarak depolanmasına olanak sağlayan yapıya Veritabanı denir.
3.1.2. MS-SQL Server Nedir ? Microsoft SQL Server en çok kullanılan veritabanı sunucu yazılımıdır. Veritabanlarının oluşturulmasını ve yönetilmesini sağlayan kurumsal çaplı Veritabanı Yönetim Sistemidir.
Dünyada en yoğun kullanılan veritabanı yönetim sistemi SQL Server’dır. SQL Server’ı kullanarak verilerinizi dilediğiniz şekilde yönetebilir, çeşitli fonksiyonları kullanarak çok sayıda ve komplike sonuçlar döndürebilirsiniz. Böylece istediğiniz verileri raporlayarak elde etmiş olursunuz.
86 | S a y f a
Microsoft SQL Server Management Studio programını çalıştırdıktan sonra server’a bağlanmak için aşağıdaki Sql Server penceresi gelmektedir. Bu pencere sistemimizde çalışan Sql Server’a (Sql sunucusu) bağlanmak için kullandığımız bilgileri ister. Bu bilgiler SQL Server Management Studio kurulurken belirlenir. Bilgilerin sunucu bilgileriyle eşleşmesiyle erişim sağlanır.
MS SQL Server Bağlantı Penceresi 1
3.1.3. SERVER TYPE Server Type’da Database Engine dışında servislerimiz bulunur. RDB-MS’de MS kısmı veritabanlarını yönetme farklı farklı hizmetler sunmayı sağlar. Burda ki servisler Raporlama Servisi, Analiz Servisi, Entegrasyon servisi gibi. Bizler veritabanlarını yönetmek için “Database Engine”’i kullanacağız.
3.1.4. SERVER NAME Server name; bir ip adresidir. Hangi server’a bağlanmak istiyorsak ip adresini Server Name alanına yazarız. Biz kendi bilgisayarımızda çalışacağımız için, kendi bilgisayarımızı server olarak kullanacağımız için, kendi bilgisayarıma girmek için Server Name’e “Bilgisayar Adını, Bilgisayarımın IP Adresini, localhost, .” yazabilirim. Farklı farklı yazmak bağlantı yolunu değiştirir.
3.1.5. AUTHENTICATION 3.1.5.1. Sql Server Authentication Sql server’a nasıl bağlanacağımızı seçiyoruz. Uzak sunucuda ki bir Server’a bağlanacağım zaman bir ip adresi gerekir. Bu ip adresi dışında veritabanına erişmek için bir kullanıcı adı ve şifre verilir. Verilen ip adresi kullanıcı adı ve şifreyle bağlantı sağlanır.
3.1.5.2. Windows Authentication Kendi bilgisayarımızdaki Sql Server’a bağlanıyorsak kullanırız. Windows Authentication seçili iken bizden kullanıcı adı ve şifre istemez. Eğer seçersek, bilgisayarda oturum açtığım kullanıcının girişi ile bağlanmayı dener.
87 | S a y f a
3.1.6. LOGIN Sql Server Authentication seçili iken Veritabanına bağlanırken hangi kullanıcı ile giriş yapacağımızı seçeceğimiz alandır. “sa” – “System Admin” veritabanları üzerinde her yetkiye sahip olan kullanıcı türüdür. Sa ile herşeyi yapabiliriz. Biz istersek kendi kullanıcılarımızıda tanımlayabiliyoruz. Kullanıcı dediğimiz bir login tanımlamaktır.
3.1.7. PASSWORD Bağlanmak istediğimiz kullancıya ait şifreyi gireriz.
3.2. MS SQL Tanıtım 3.2.1. Object Explorer Veritabanlarını yönetebildiğimiz pencere. İş tanımlama, servisler gibi işlemlerin tanımlandığı yerler bulunur. Biz security ve databases ile ilgileneceğiz. Database’de sorgulama yapmayı öğrenmek için Microsoft’un bize sunduğu hazır bir DataBase’i kullanacağız. Northwind diye geçer. Hazır tabloları ve verileri bulunan üzerinde sorgulamalar yapabildiğimiz bir veritabanıdır. Sql’in öğrenilmesi için hazırlanmıştır.
3.2.2. New Database DATABASE NAME : Veritabanımıza vermek istediğimiz isim. OWNER : Default bıraktığınızda giriş yaptığınız kullanıcının bu veritabanına sahip olduğunu söyler. Bazen sıkıntı çıkarabiliyor. İstersek direkt olarak yöneticinin adını yazabiliriz.
LOGICAL NAME : Database için açılacak dosyaların isimleridir.
FILE TYPE : Dosya tipimizi belirler. SQL’de dosya tipi ikiye ayrılır. 1. MDF (Meta Data File) 2. LDF (Log Data File) Mdf : Veritabanına girmiş olduğum verilerin aslı tutulur. Yani veritabanına eklediğim bilgilerin kendisi tutulur.
88 | S a y f a
Ldf : Log dosyasıdır. Veritabanında yapılan işlemlerin loglarını tutar. (Şu kullanıcı şu ip’den giriş yaptı, şu bilgiyi güncelledi gibi..)
FILE GROUP : Veritabanını parçalamak için kullanılır. Primary yazıyor. İstersem Secondary diye bi grup daha açarım bu da farklı bi diskte farklı bir alanı tutabilirim. Veri kurtarmakda ve performanslı çalışmasında işe yarar.
INITIAL SIZE : Açılacak olan dosyanın başlangıçta ne kadar bir boyutta olacağını sorar. Burda ki ilk değerler varsayılan değerdir. İstersem bu değeri yükseltebilirim ama Sql server 2008 için bu değer 3mb’den, Sql Server 2012 için bu değer 4mb’den az olamaz.
AUTOGROWTH : Otomatik artış değeridir. Veritabanı içerisindeki veriler veritabanı boyutunun sınırına ulaştığında bu alanda belirlenen değer kadar veritabanı boyutu arttırılır.
3.2.3. Database İçerisindeki Yapılar Database Diagrams : Database tablolarını ve tablolar arasındaki ilişkiyi görüp yönetmek için kullandığım görsel kısımdır. Tables : Database içerisinde bulunan tablolarımızın bulunduğu kısımdır. Views : View’larımızın bulunduğu kısımdır. Security : Database güvenliğidir. Database’e hangi kullanıcılar bağlanabilir ve hangi işlemleri yapabilir gibi bilgilerin tutulduğu kısımdır. Programmability : Kendi yapılarımızı tanımlayıp veritabanına aktarabildiğimiz kısımdır.
3.2.4. SQL’de ki Data Type’lar Sql’de birden fazla string ifade bulunur. (char, varchar, nchar, nvarchar) Yanlarına parantez içerisinde yazdığım değer kaç karakter girebileceğimi belirtir. (var : Variable’dan gelir. Değişken karakter anlamını taşır)
char(10) : Belirlediğim kadar boşluk açar ve söylediğim karakter sayısından az kaç karakter kullanırsam kullanayım verdiğim karakter sayısı kadar yer tutar. nchar(10) : Char’ın tüm karakterleri destekleyen hali
89 | S a y f a
varchar(10) : Belirlediğim kadar boşluk açar ve söylediğim karakter sayısından az kaç karakter kullanırsam tuttuğu alanı o kadar karaktere düşürür ve daha az kaynak harcar. nvarchar(10) : varchar’ın tüm karakterleri destekleyen hali int : Sayısal değerleri tutar. bit :Boolean değer tutar. datetime : Tarih ve saat formatında değer tutar. date : Tarih formatında değer tutar.
3.3. NORMALİZASYON
SQL kullanılırken bir matematikçi Sql tablo yapısını inceliyor.Ve tekrar eden verilerin olduğunu farkediyor. Bu verilerin kullandığı kaynak (yer) boşa harcandığından daha güzel bir yöntem geliştiriyor. Normalizasyon (Ayrıştırma), veritabanlarında çok fazla sütun ve satırdan oluşan bir tabloyu tekrarlardan arındırmak için daha az satır ve sütun içeren alt kümelere ayrıştırma işlemidir. Ünlü Fransız bilim adamı Hubert Francesci tarafından ortaya atılan 3 esnek kuralına uygun protonlar tarafından entegre edilen bir sisteme sahiptir. Satır başlarında yapılan tekrar veritabanında ayrıştırma işlemine tabii tutularak depolanır.
1NF (Birinci Normal Form): Bütün niteliklerin öz alanından (domain) aldığı değerler atomik olmak zorundadır. İlişkisel veri tabanı modelinin temel kuralıdır ve her nitelik ancak atomik veriler alabilir. Örneğin kitap tablosunda, birden fazla yazarı olan kitap için yazar1, yazar2, yazar3 diye alanlar açsaydık, bu kurala uymamış olurduk. Böyle bir durumda, ayrıca yazarlar tablosu da oluşturarak kuralı çiğnememiş oluruz.
2NF (İkinci Normal Form): Eğer R’deki herhangi bir birincil olmayan nitelik A, R’nin hiçbir anahtar niteliğine kısmi fonksiyonel bağımlı değilse bu ilişki şeması 2NF’dir denir. Burada kısmi fonksiyonel bağımlılıktan şunu anlamalıyız: Eğer X --> Y geçerli ise ve bir nitelik A X’in elemanı ise ve A, X’ten çıkarıldığı halde söz konusu bağımlılık hala geçerli ise burada bir kısmi fonksiyonel bağımlılık vardır.
3NF (Üçüncü Normal Form): Eğer R’deki herhangi bir birincil olmayan (non-prime) nitelik A, R’nin hiçbir anahtar niteliğine geçişli (transitively) fonksiyonel bağımlı değil ve hali hazırda 2NF’da ise, bu ilişki şeması R 3NF’dadır denir. Burada geçişli fonksiyonel bağımlılıktan şunu anlamalıyız: Eğer X --> Y ve R’nin herhangi bir anahtarının altkümesi olmayan nitelikler kümesi Z söz konusu ve de X --> Y ve Y --> Z birlikte geçerli olmamalıdır.
Bire – Bir İlişki Bire – Çok İlişki Çoka – Çok İlişki
3.4. Veritabanı Taşıma ve Yedekleme İşlemleri 3.4.1. Back-Up Restore Yöntemi Database’e sağ tıklanır. Task sekmesi altında Back-Up seçeneği seçilir. (Örneğin C:’nin altına bir BackUp klasörü oluşturalım.) Dilersek Management klasöründen bir iş tanımlayarak belirtilen tarih ve saatte yedek alınmasını sağlayabiliriz. Database : Hangi database’in backup’ı alınacaksa o database seçilir. Backup Type : Full : Database’in tamamen yedeğini alır. Differential : Daha önceden alınan bir yedek varsa o yedeğin üstüne yeni verileri yedekler. Transaction Log : Log dosyasının yedeğini alır. ********************** NOT : Backup alınırken varsayılan adresi silip kendi adresimizi vermemiz gerekir aksi taktirde hata verir. ********************** BACKUP Dosyasından Veritabanını Yükleme : Database’e Sağ Tıklayıp > Restore Database
91 | S a y f a
Backup dosyasını dışarıya kayıt ettiğimiz için Device seçilir. Burda backup’ı aldığımız klasör içerisinde .bak uzantılı dosyayı seçeriz. Gerekli ayarlamaları yaparak OK butonuna bastığımızda veritabanı restore edilir.
3.4.2. ATTACH – DETACH Yöntemi Database’I başka bir yere taşımak veya taşınan bir şeyi Sql Server’a eklemenin bir başka yöntemidir. Bilgisayarımı açıyoruz.. ProgramFiles>Microsoft Sql Server > MSSQL11.MSSQLSERVER >MSSQL > DATA klasörü içerisinde bizim bütün databaselerimiz mevcuttur. Bunları kopyala yapıştır ile buradan alabiliriz. ********************** NOT : Direk kopyalamaya çalışırsak hata verir. Bunun sebebi SQL serverin servisinin çalışması ve bu dosyaları koruma altına almasıdır. SQL servisini kapatarak kopyalama işlemini yapabiliriz. Servisi Durdurmak için; Bilgisayarım Sağ Tık > Yönet > Servisler > Sql Server (MSSQLSERVER) olanı durdururuz. Ama bu server’ı durdurursak Sql Server’a giriş yapamayız. **********************
3.4.3. GENERATE SCRIPTS Taşımak istediğimiz Database’e sağ tıklayıp Task > Generate Scripts diyoruz. Açılan wizard’da ki yönergeleri izliyoruz. İlk pencerede scripti çıkarılacak olan bilgileri seçiyoruz. (Database’in tamamı veya istediğimiz tablolar). Advance seçeneğinden Type of data to script seçeneğini düzenlememiz gerekir. Schema Only : Sadece şemanın scriptini çıkarır. Data Only : Sadece verilerin scriptini çıkartır. Schema and Data : Database şemasını ve dataları birlikte script olarak çıkarır. File Name : Database scriptinin nereye kayıt edileceğinin bilgisini ister.
3.5. TRANSACT SQL New Query : Sql sgularını yazdığımız alandır. Execute (F5) : Sql sorgularını çalıştırmak için kullandığımız butondur. Veritabanı Seçimi : Hangi veritabanı ile çalışacaksan seçim yapmamız gerekir. Not : Query dosyasını kayıt etmek istediğimizde uzantısı .sql olur.
92 | S a y f a
MS-SQL’de Bizim kullandığımız dil T-SQL’dir.
T-SQL’de Diller Üçe Ayrılır. 1. DDL (Data Definition Language) 2. DML (Data Manupulation Language) 3. DCL (Data Control Language)
3.5.1. Data Definition Language – DDL
Create, Alter, Drop komutlarını içerir. Database’de nesne oluşturur. Create ile oluşturur, Alter ile günceller ve Drop ile nesneyi silebiliriz. Bir nesne oluşturmak istediğimizde DDL komutlarını kullanırız. Database Nesnelerinden Bazıları Database Tablolar Diagram View Stored Procedure Trigger Bunları oluştururken DDL komutu kullanılır.
Kod ile yeni bir veritabanı oluşturmak CREATE DATABASE KodIleDB ON PRIMARY --Datalarin tutuldugu dosya ( Name = "KodIleDB_Data", FileName = 'C:\Backups\KodIleDB.mdf', --Slash işaretine dikkat Size = 4mb, --Boyutu Size FileGrowth = 1mb ) LOG ON --Dikkat ( Name = "KodIleDB_Log", FileName = 'C:\Backups\KodIleDB.ldf', Size = 1mb, FileGrowth = 10% )
Kod ile yeni bir tablo oluşturmak use KodIleDB CREATE TABLE Tablom --Tablo Adi ( ID int identity(1,1) primary key, --Adı ID olsun, tipi int olsun, identity kolonu (1 den başlasın 1-1 artsın ve primary key olsun) Ad nvarchar(50) not null, --Boş geçilemez
93 | S a y f a
Soyad nvarchar(50) )
3.5.2. SYSTEM DATABASES
New Query ekranı açtığımda burda System Database içerisinde Master Model Msdb Tempdb veritabanları vardır. Sistemden gelen veritabanlarıdır. Bunları hiç bir şekilde silmememiz gerekir. Bunları silmek demek SQL Server’ı silmek anlamına gelir.
Master : Sql içerisindeki hazır yapıları barındıran database’dir. Select * from sys. --Yazdığımda
gelen tüm veriler master’dan gelir.
Model : Sql Server ile ilgili hazır yapıları bulundurur. Örneğin yeni bir database açtığımda gelen initial size, autogrowth gibi bilgilerin default değerleri burdan gelir.
Msdb : Zamanlanmış görevleri, görev olarak tanımlanan yapılar msdb içerisinde tutulur.
Tempdb : Geçici olarak kullanılan, Ramde tutup aktarmaya çalışılan bilgiler için kullanılır.
3.5.3. Northwind Script Microsoft’un SQL’i öğrenme amaçlı bize sunduğu bir database dosyasıdır. Sorgulamayı bu database üzerinde öğreneceğiz. Northwind kurarken İki hata çıkacaktır bu hatalar stored procedure ile ilgilidir.
3.5.4. Data Manupulation Language – DML
Select, Insert, Update ve Delete komutlarını içerir. Veritabanıma kayıt olmuş veya kayıt olacak verileri yönetebilmek için kullanılan dildir. Kayıt eklemek için Insert, kayıt güncellemek için Update, kayıt silmek için Delete, kayıtları listelemek için select komutu kullanılır. 3.5.4.1. SELECT SORGULARI
Örnek Sorgu --Urunleri listeleyen sorgu use Northwind SELECT * --Benim için * tüm kolonları simgeler FROM Products
94 | S a y f a
Yukarıda kullanılan * ifadesi belirtilen tablodaki tüm kolonları temsil etmektedir. * ifadesini kullanarak tabloda bulunan bütün kolonları sorgu sonucunda görüntüleyebilirim.
Örnek Sorgu --Urunler tablosunda urunid, urunadi, fiyati, stoktaki miktari bilgilerini cekmek icin Select Products.ProductID, Products.ProductName, Products.UnitPrice, Products.UnitsInStock FROM Products
Yukarıda ki örnekte * yerine kolon isimlerini belirleme işlemini yaptık. Belirtilen tabloda, belirlediğimiz kolonların sorgu sonucunda görüntülenmesini sağladık.
Anlatılacak Örnek --Veri çekme işleminde daha kolay yöntem olan tabloya isim vermek Select p.ProductID, p.ProductName, p.UnitPrice, p.UnitsInStock –Son kolondan sonra , eklenmez FROM Products p –Products tablosuna p diye isim veririz.
Tablolarımıza isim verip bu isimleri kullanarak intellisense desteğini arttırabiliriz. Tablomuzu temsil edecek bir isim kullanarak kolon erişimlerini daha hızlı bir şekilde sağlayabiliriz. Yukarıda ki örnekte Products tablosunu temsil etmesi için ‘p’ harfini atadım. Ben sorgu içerisinde p harfini yazdığımda bu harf Products tablosunu temsil edecektir.
Bilgi : Sql kodlarını yukarıdaki formatta yazmak zorunda değiliz. Ama sql’de intellisense desteği çok iyi olmadığından kodları okumam yazmam ve anlamam zorlaşacağından yukarıdaki formatta yazılmasını tavsiye ederim.
SQL İpuçları
Tools>Options>Text Editor > All Languages > Word Wrap seçersek satır sonuna gelince alt satıra geçer. Tools>Options>Text Editor > All Languages > Line Numbers satır numaralarını açar
95 | S a y f a
Örnek Sorgu --Tedarikciler(Suppliers) tablosundan Sirket Adi(CompanyName), Yetkili Kisi(ContactName), Telefon(Phone), Sehir(City), Ulke(Country) ve Adres(Address) bilgilerini getiren sorgu SELECT s.CompanyName, s.ContactName, s.Phone, s.City, s.Country, s.Address FROM Suppliers s
Yukarıdaki sorguda Adress sözcüğünün renginin mavi olduğu görülmekte, bu renk sql de tanımlı olan yapıların rengidir. Address kelimesi sqlde tanımlı olduğu için rengi mavi çıkmaktadır. Yukarıda ki sorgu çalışırken bir problem ile karşılaşılmaz. Bu kelimenin Sql’de tanımlı olan değilde, bizim oluşturduğumuz bir kelime olduğunu belirtmek için Address kelimesini köşeli parantezler içerisine alabiliriz.
Örnek Sorgu --Tedarikciler(Suppliers) tablosundan Sirket Adi(CompanyName), Yetkili Kisi(ContactName), Telefon(Phone), Sehir(City), Ulke(Country) ve Adres(Address) bilgilerini getiren sorgu SELECT s.CompanyName, s.ContactName, s.Phone, s.City, s.Country, s.[Address] FROM Suppliers s
Address kelimesi köşeli parantezler içerisine alındığında, rengi değişecektir. Sql de tanımlı kelimeler dışarısında arasında boşluk olan kelimelerde köşeli parantez içinde yazılarak tek bir ifadeye dönüştürülebilir.
3.5.4.2. Kolonlara İsim Vermek Yazdığımız sorgularda kolonların isimlerini daha anlamlı olarak göstermek isteyebiliriz veya kullanıcılara verilecek bir sorgu sonucunda kolon isimlerimizi kullanıcılara göstermek doğru bir yöntem değildir. Aşağıdaki örnek sorguyu inceleyecek bir kolonu farklı bir isimle sorguda gösterme yöntemlerini bulabilirsiniz.
Örnek : Kolonlara isim vermek --Tedarikciler(Suppliers) tablosundan Sirket Adi, Yetkili Kisi, Telefon, Sehir, Ulke ve Adres bilgilerini getiren sorgu SELECT
96 | S a y f a
s.CompanyName as ‘Şirket Adı', --Tek Tırnaklar Sql'de string'dir. s.ContactName 'Yetkili Kişi', --As ifadesini kullanmadanda kolon ismi verebiliriz. s.Phone as Telefon, --Türkçe karakter ve boşluk kullanmadığımızda tercih edilebilir s.City as [Sehir], --Verilen ifadede türkçe karakter yok ve boşluk varsa kullanılabilir s.Country, s.[Address] FROM Suppliers s
3.5.4.3. SELECT SORGULARI (Where – And, Or, Between, In, Not In) Listelemek için kullanılan select sorgularında filtrelemeler yapabiliriz. Belirli değer aralıklarında bulunan sonuçları göstermek için kullanılan Sql söz dizimleri bulunmaktadır.
3.5.4.4. WHERE Sorgusu Sql de listeleme işlemi sonucunda dönen listedeki değerleri filtrelemek için kullanılan söz dizimidir. Select sorgusu ile birlikte kullanılır. Select sorgusundan sonra yazılan where sorgusu, select ile listelenecek olan verileri belirlediğimiz şarta göre listeler.
WHERE
Örnek Sorgu --Fiyatı 20$'dan az olan urunleri getiren sorgu SELECT * FROM Products p WHERE p.UnitPrice < 20
Örnek Sorgu --Fiyatı 20 ile 50 arasında olan ürünlerin urunadi, fiyat bilgilerini getiren sorgu SELECT * FROM Products p WHERE p.UnitPrice > 20 AND --20 Dahil Değil p.UnitPrice < 50 --50 de Dahil Değil
3.5.4.5. BETWEEN Kullanımı İki değer aralığında sonuçları listelemek için kullanabiliriz. Belirtilen aralıktaki sonuçları listeler. Select sorgularında, Where ile birlikte kullanılır.
Örnek Sorgu : Between --Fiyatı 20 ile 50 arasında olan ürünlerin urunadi, fiyat bilgilerini getiren sorgu SELECT * FROM Products p WHERE p.UnitPrice BETWEEN 20 and 50 --20 dahil, 50 dahil değil
97 | S a y f a
Önemli : Sql'de String ifadeler için 'tek tırnak' kullanılır.
Örnek Sorgu – Where --Londra(London) veya Paris de olan müşterilerin(Customers) Şirket adi, Yetkili kisi bilgisi, sehir ve adres bilgilerini getiren sorgu SELECT c.CompanyName, c.ContactName, c.City, c.[Address] FROM Customers c WHERE c.City = 'Paris' OR c.City = 'London'
Örnek Sorgu – Where Kullanarak --Londra(London) olmayan müşterilerin(Customers) Şirket adi, yetkili kisi bilgisi, sehir ve adres bilgilerini getiren sorgu SELECT c.CompanyName, c.ContactName, c.City, c.[Address] FROM Customers c WHERE c.City != 'London'
3.5.4.6. IN Belirtilen kolon içeriğinin içerisinde belirtilen değerlerin bulunup bulunmadığını kontrol eden söz dizimidir. Kontrol edilen hücrenin içeriği, IN içerisinde belirtilen değerlerden bir tanesine eşitse listeleme işlemi yapılır. Select sorgularında, Where komutu ile birlikte kullanılır.
Örnek Sorgu – IN Kullanarak --Londra(London), Berlini Madrid veya Paris'de olan müşterilerin(Customers) Şirket adi, yetkili kisi bilgisi, sehir ve adres bilgilerini getiren sorgu SELECT c.CompanyName, c.ContactName, c.City, c.[Address] FROM Customers c WHERE c.City IN ('London', 'Paris', 'Madrid', 'Berlin')
Örnek Sorgu – NOT IN Kullanarak --Londra(London), Berlini Madrid veya Paris'de olmayan müşterilerin(Customers) şirket adi, yetkili kisi bilgisi, sehir ve adres bilgilerini getiren sorgu SELECT
98 | S a y f a
c.CompanyName, c.ContactName, c.City, c.[Address] FROM Customers c WHERE c.City NOT IN ('London', 'Paris', 'Madrid', 'Berlin')
3.5.4.7. LIKE Sql’de veriler içerisinde benzerlik sorgusu yapar. Verilen değerin, REGEX METOTLARINA göre veri içerisinde bulunup bulunmadığını kontrol eder. Select sorgularında, Where komutu ile birlikte kullanılır.
Örnek Sorgu - LIKE --Sirket Adinda 'restaurant' gecen musterilerin(Customers) bilgilerini getiren sorgu SELECT * FROM Customers c Where c.CompanyName LIKE '%restaurant%' --Saga ve sola koyulan yuzdeler, yuzde olan yerde kac karakter ve bu karakterlerin ne oldugu fark etmez anlamina gelir.
Bilgi : Arama sırasında büyük küçük harf duyarlılığı yoktur.
REGULAR EXPRESSION – REGEX METOTLARI
% _ ^x
Eklendiği yerde kaç karakter ve hangi karakter olduğu önemli değil Tek karakter ama hangi karkater olduğu önemli değil Verilen karakter olmayan
REGEX Örnekleri
‘__a%’ ‘__a_’
3. Harfi a olan ürünler. 4 karakterli ve 3. Harfi a olan ürünler
SORGU YAZARKEN İZLENECEK YÖNTEM 1. 2. 3. 4.
Hangi komutu kullanacağına karar ver. (SELECT) Hangi tablo ile çalışacağına karar ver. Hangi kolonları görüntüleyeceğine karar ver. Varsa kullanacağın kriterleri belirt.
Örnek Sorgu : Like --Ürün Adı c ile başlayan ve 3. harfi a olan ürünlerin bilgilerini getiren sorgu SELECT *
99 | S a y f a
FROM Products p Where p.ProductName LIKE 'c_a%'
Örnek Sorgu : Like --c ile başlayan 4. harfi a olan ve 5 harfli ürünleri getiren sorgu SELECT * FROM Products p WHERE p.ProductName LIKE 'c__a_'
Örnek Sorgu : Like --c ile başlayan 3.harfli a ile k arasında olan ürünleri getiren sorgu SELECT * FROM Products p WHERE p.ProductName LIKE 'c_[a-k]%'
Örnek Sorgu : Like --c ile başlayan ve 3. harfi a olmayan ürünleri getiren sorgu SELECT * FROM Products p WHERE p.ProductName LIKE 'c_[^a]%'
Örnek Sorgu : Like --İkinci harfi o olan ve meat ile biten ürünlerin bilgilerini getiren sorgu SELECT * FROM Products p WHERE p.ProductName LIKE '_o%meat'
Örnek Sorgu : Like --Fax numarası boş olan (Null) müşterilerin bilgileri --DİKKAT : '' olan değil SELECT * FROM Customers c WHERE c.Fax Is NOT Null
3.5.4.8. ORDER BY Sıralama işlemlerini yapar, sıralama işlemleri yazılan sorgudan sonra belirtilir. Order By söz dizimi iki değer alır. Bu değerlerden biri ASC, diğeri DESC değeridir. ASC (Ascending) : Numeric ve Alfanumeric olarak artan sıralama yapar. DESC (Descending) : Numeric ve Alfanumeric olarak azalan sıralama yapar. Order By söz diziminin default olarak aldığı değer ASC değeridir.
100 | S a y f a
Örnek Sorgu : Order By --Ürünleri isimlerine göre sıralama SELECT * FROM Products p ORDER BY p.ProductName
Örnek Sorgu : Order By --Ürünlerin ürün adı, fiyatı ve stokdaki miktarını ürün fiyatına göre tersten sıralayan sorgu SELECT p.ProductName, p.UnitPrice, p.UnitsInStock FROM Products p ORDER BY p.UnitPrice DESC
Örnek Sorgu : Order By --Kolon adlarını istersek sıra numarası ile verebiliriz. Ama bunun bir zararı vardır. Kolon sıralaması değişebilir.. SELECT p.ProductName, p.UnitPrice, p.UnitsInStock FROM Products p ORDER BY 2 DESC
Örnek Sorgu : Order By ve Between --01.01.1996 ile 31.12.1996 tarihleri (1996 yılındaki) arasındaki siparişlerin SiparişID, SiparişTarihi, Sehir ve Ülke Bilgilerini tarih kolonuna göre tersten sıralayan sorgu --1.Yöntem SELECT o.OrderID, o.OrderDate, o.ShipCity, o.ShipCountry From Orders o --Where o.OrderDate >= '01.01.1996' and o.OrderDate <= '12.31.1996' WHERE o.OrderDate BETWEEN '01.01.1996' and '12.31.1996' ORDER BY o.OrderDate DESC --2.Yöntem SELECT o.OrderID, o.OrderDate, o.ShipCity, o.ShipCountry FROM Orders o WHERE YEAR(o.OrderDate) = 1996 ORDER BY o.OrderDate DESC
101 | S a y f a
3.5.4.9. ZAMAN METOTLARI Tarihler ile ilgili işlemleri yapmak için kullanılan yardımcı metotlardır. Verilen tarihden istenilen değeri döndürebilirler. En çok kullanılan zaman metotları aşağıdadır.
YEAR(tarih) : Girilen tarihin yıl bilgisini verir. MONTH(tarih) : Girilen tarihin ay bilgisini verir. DAY(tarih) : Girilen tarihin gün bilgisini verir. GETDATE() : Şu anki sistem tarihini verir.
Örnek Sorgu --01.09.1996 ile 31.12.1996 tarihleri arasındaki siparişlerin SiparişID, SiparişTarihi, Sehir ve Ülke Bilgilerini tarih kolonuna göre tersten sıralayan sorgu SELECT o.OrderID, o.OrderDate, o.ShipCity, o.ShipCountry FROM Orders o WHERE YEAR(o.OrderDate) = 1996 and MONTH(o.OrderDate) > 9 ORDER BY o.OrderDate DESC
Örnek Sorgu --Doğum günü bugün olan çalışanların adsoyad, doğum tarihini ve ünvanını getiren sorgu (AdSoyad bilgisi tek kolonda gelecek) SELECT e.FirstName + ' ' + e.LastName AS 'Ad Soyad', e.BirthDate, e.Title FROM Employees e WHERE MONTH(e.BirthDate) = MONTH(GETDATE()) and DAY(e.BirthDate) = DAY(GETDATE())
3.5.4.10. AGGREGATE FUNCTION – Bütünleşik Sorgular SUM() : Toplama Fonksiyonu. Tüm değerlerin toplam sonucunu elde eder. AVG() : Ortalama Almak için kullanılan fonksiyondur. Verilen değerlerin ortalamasını alır. Count() : Verilen tablodaki satırları sayan metotdur. MAX() : Verilen kolondaki maximum değeri bulur. MIN() : Verilen kolondaki minimum değeri bulur. ROUND() : Dönen sonuçta virgülden sonraki değeri yuvarlar.
102 | S a y f a
Örnek Sorgu --Şu ana kadarki toplam ciro / (Order Details Tablosu) Fiyat*Adet*(1-indirim) SELECT SUM(od.Quantity * od.UnitPrice*(1-od.Discount)) AS 'Toplam Ciro' --Başına SUM yazmazsak her kolondan gelen değeri yazdırır. FROM [Order Details] od
Örnek Sorgu : Round ve Sum --Noktadan sonra bir çok değer var bunu düzenlemek içinde Round metodu kullanılır. SELECT ROUND(SUM(od.Quantity * od.UnitPrice*(1-od.Discount)), 2) AS 'Toplam Ciro' --Round değeri yuvarlar. FROM [Order Details] od
/******AGGREGATE FUNCTION'LAR BANA TEK BiR DEĞER DÖNDÜRÜR********/
Örnek Sorgu : Sum --Bügüne kadar kaç ürün satılmış SELECT SUM(od.Quantity) AS 'Toplam Adet' FROM [Order Details] od
Örnek Sorgu : Count --Bugüne kadar kaç adet sipariş alınmış SELECT COUNT(o.OrderID) AS 'Toplam Sipariş Sayısı' --Count kullanırken herhangibi bir kolonu verebiliriz. --Kolon yerine * dersek kolon adı vermemiz gerekmez. FROM Orders o
Örnek Sorgu : Max --Şu an ki fiyatı en pahalı ürünün fiyatı nedir SELECT MAX(p.UnitPrice) as 'En Pahalı Fiyat' FROM Products p --2.Yöntem SELECT TOP 1 p.UnitPrice FROM Products p Order By p.UnitPrice DESC
Örnek Sorgu : AVG --Ürünlerin ortalama fiyat bilgisi SELECT AVG(p.UnitPrice) AS 'Ortalama Fiyat'
103 | S a y f a
FROM Products p
3.5.4.11. SUB QUERY – ALT SORGULAR Sql sorgularımızda gerekli durumlarda alt sorgular kullanmamız gerekebilir. Alt sorgulardan dönen değerler kullanılarak çeşitli sorgulama işlemleri yapılır. Alt sorgu kullanırken dikkat etmemiz gereken noktalar vardır.
Alt sorgular her zaman tek bir değer döndürmelidir. Alt sorgular parantezler içerisinde yazılır. Alt sorgularda matematik de ki gibi önce parantez işlemi içerisinde ki sorgu çalıştırılır. Alt sorgular performansı olumsuz etkiler.
Fiyatı ortalama fiyatın altında olan ürünleri listeleyen bir sorgu yazmak istediğimizde, bu sorgunun dinamik olmasını isteriz. Aşağıdaki örnekleri inceleyerek Sub Query kullanımını inceleyebilirsiniz.
Örnek --Ürünlerin ortalama fiyat bilgisi SELECT AVG(p.UnitPrice) AS 'Ortalama Fiyat' FROM Products p --Fiyatı ortalama fiyatın altında ürünleri getiren sorgu SELECT --Yanlış gösterim Syntax olarak hata vermez ama gösterim yanlıştır. * FROM Products p WHERE p.UnitPrice < AVG(p.UnitPrice)
Yukarıdaki sorgu syntax olarak hata vermez ama mantıksal olarak hatalıdır.
Yukarıdaki Kod çalıştığında aşağıdaki hata verilecektir. AGGREGATE FUNCTION'LAR Where içerisinde kullanılamaz. Ya Having Kullanım yada dışarıdan aldığın değeri referans olarak gösterin. (yani Sub Query Kullanım)
AVG'yi kullanıp tüm ürünleri hesaplayabilmek için tüm ürünlerin bilgisine ihtiyacımız var. Bu işlemi yapabilmemiz için tüm ürünlerin bilgisinden bir ortalama çıkarıp daha sonra ürünleri listelemem gerekmektedir.
Örnek : Tüm ürünlerin ortalama fiyat bilgisini getiren sorgu SELECT AVG(p.UnitPrice)
104 | S a y f a
FROM Products p
Yukarıdaki kod ile ortalama fiyatı hesaplatıp aşağıya sonucunu yazabiliriz. ama bu bizim için dinamik olmaz.
Örnek : Ürünlerin Ortalama Fiyatını Bulmak SELECT * FROM Products p Where p.UnitPrice < 28.65
Sub query kulanarak, fiyatı ortalama fiyatın altında olan ürünleri listeleyelim.
Örnek : Fiyatı Ortalama Fiyatın Altında Olan Ürünleri Listeleyen Sorgu SELECT * FROM Products p WHERE p.UnitPrice < ( SELECT AVG(p.UnitPrice) --Alt sorgudan dönen değer üst sorguya kriter olarak gitti FROM Products p )
--Alt Sorgulardada matematikde ki gibi önce parantez içerisindeki işlem yapılır.*/ --Alt sorgular performansı olumsuz etkiler ama kullanmamız gereken durumlar olur. --Alt sorgular yanlızca bir değer döndürmelidir.
3.5.4.12. TOP ve DISTINCT Top : Yazılan sorgudan dönen sonuç içinde en üstte çıkan x adet sonucu gösterir.
Örnek : Top --En pahali 3 urunu getiren sorgu SELECT TOP 3 * FROM Products p Order By p.UnitPrice DESC
Distinct : Tekrar eden değerleri egale etmek için kullanılır.
Örnek : Distinct --Hangi ulkelere is yapiyoruz SELECT DISTINCT
105 | S a y f a
c.Country FROM Customers c
Örnek : Top --Ilk ise aldigim calisanim hangisi SELECT TOP 1 * FROM Employees e WHERE e.HireDate IS NOT NULL ORDER BY e.HireDate ASC
Örnek : Aggregate Function ve Distinct --Kac Farkli ulkeye siparis gonderilmis – Ulke Sayısı SELECT COUNT(DISTINCT o.ShipCountry) FROM Orders o --Yukarıdaki örnekde tüm satıları sayıyor. Ama benim ülkeleri önce ayırıp sonra saydırmam gerekiyor.
3.5.4.13. GROUP BY Aggregate Function’lardan dönen değeri kolonlara göre parçalamak(gruplamak) için kullanılır. Dönen değerler belirtilen kolonlara göre parçalanarak tablo oluşturulur. Aggregate Function kullandığımızda, sorgu sonucunda birden fazla kolon görüntülemek istersen bir hata ile karşılaşırız. Bu hata bir kolonda tek değer, diğer kolonda birden fazla değer döndüğünden kaynaklanmaktadır. Bizim verileri tablo yapısında göstermek için Aggregate function’dan dönen değeri kolona göre parçalamamız gerekmektedir. Aggregate Function dışında kalan tüm kolonlar Group By ‘da belirtilmek zorundadır.
Anlatılacak Örnek --Kategoriye gore urun sayilarini getiren sorgu SELECT p.CategoryID, COUNT(*) as 'UrunSayisi' FROM Products p GROUP BY p.CategoryID
Örnek --Kategoriye gore urun sayilarini getiren sorguda iki kolon kullanmak SELECT p.CategoryID, p.ProductName, COUNT(*) as 'UrunSayisi' FROM Products p GROUP BY p.CategoryID, p.ProductName
106 | S a y f a
Aggregate Function dışında yazılan kolon isimlerinin her biri GROUP BY’da belirtilmek zorundadır.
Örnek --Ulkelere gore calisan sayisini veren sorgu SELECT e.Country, COUNT(*) FROM Employees e GROUP BY e.Country
Örnek --Calisanlarin ID'lerine gore calisanlarin almis olduklari siparisleri getiren sorgu SELECT o.EmployeeID, COUNT(*) FROM Orders o GROUP BY o.EmployeeID
Örnek --Her kategoride ucret bazli toplam ne kadarlik urun oldugu bilgisini veren sorgu SELECT p.CategoryID, SUM(p.UnitPrice * p.UnitsInStock) as 'Gelir' FROM Products p GROUP BY p.CategoryID
3.5.4.14. JOIN (BİRLEŞTİRME) İlişkisel tablolarda raporlama yaparken ID bilgileri önemsizleşir. Çünkü ID bilgileri anlamlı bilgiler değildir. Aşağıdaki sorguyu yazıp çalıştırdığımızda bize sorgumuzun altında yer alan resimdeki gibi bir sonuç dönecektir.
Örnek Sorgu SELECT * FROM Products
107 | S a y f a
Yukarıdaki resimde bulunan SupplierID ve CategoryID kolonları ilişkisel tablolarda anlamlı bilgilerdir fakat raporlama yapıldığında anlamlı ifadeler olmaktan çıkar. Biz bu raporu hazırladığımızda inceleyen kişi için id değerleri bir anlam ifade etmez bu sebepten, id yerine anlamlı ifadeler olan Tedarikçi İsimleri, Kategori isimleri vb. bilgileri raporlamamız gerekmektedir.
Birden fazla tablodan veri çekmek için aşağıda ki Join kullanılır. Join komutları ve açıklamalarını aşağıda bulabilirsiniz. 3.5.4.14.1.
Join Çeşitleri
Inner Join : Eşleşen kayıtları getirir. Left Join : Verdiğim yöne göre, o yöndeki tüm kayıtları getirir. Left Join tanımlandığında sol taraftaki tüm kayıtları getirir. Yönünü verdiğim taraftaki tüm verileri getirir, diğer taraftaki bilgiler içerisinde null değer olabilir anlamına gelir. Right Join : Verdiğim yöne göre, o yöndeki tüm kayıtları getirir. Right Join tanımlandığında sağ taraftaki tüm kayıtları getirir. Yönünü verdiğim taraftaki tüm verileri getirir, diğer taraftaki bilgiler içerisinde null değer olabilir anlamına gelir.
Örnek Sorgu --Calisanlarin ID'lerine gore calisanlarin almis olduklari siparisleri getiren sorgu SELECT o.EmployeeID, COUNT(*) FROM Orders o GROUP BY o.EmployeeID
Aşağıdaki resimde bulunan sorgu sonucu bizim için anlamlı bir ifade değildir.
1 numaralı ID’ye sahip çalışan 123 sipariş almış, Ama 1 numaralı çalışan kim, bilgileri neler id değerleri bizim için anlamsız olduğundan raporlamalarda bu şekilde kullanılamaz. Bu sonuçta ID yerine isim soyisim yazdığımızda daha anlamlı bir sonuç elde edebiliriz.
108 | S a y f a
Syntax : Join İşlemleri SELECT ., ., ., . FROM (INNER) JOIN ON . = .
Yukarıda birbirine eşitlenen iki kolon referans kolonlarıdır. Inner Opsiyoneldir.
Aşağıda ki örnek çalışanlara göre sipariş sayısını veren sorgudur. İki farklı tablodan veri çekerek anlamlı sorgu sonuçları elde edebiliriz.
Örnek Sorgu SELECT e.EmployeeID, e.FirstName, e.LastName, COUNT(*) as 'Siparis Sayisi' FROM Employees e INNER JOIN Orders o ON e.EmployeeID = o.EmployeeID GROUP BY e.EmployeeID, e.FirstName, e.LastName ORDER BY 2 DESC
Örnek Sorgu --Kategori Adi, Tedarikci Adi ve Urun Adini getiren sorgu SELECT p.ProductName, c.CategoryName,
109 | S a y f a
s.CompanyName FROM Products p INNER JOIN Categories c ON c.CategoryID = p.CategoryID INNER JOIN Suppliers s ON s.SupplierID = p.SupplierID
Örnek Sorgu --Federal Shipping ile tasinmis(Shippers - Company Name) ve Nancy'nin(Employees FirstName) uzerine kayıtlı olan siparislerin CalisanID, Calisan Adi Soyadi, SirketAdi, SiparisID, Siparis Tarihi, Kargo Ucretini getiren sorgu SELECT e.EmployeeID, e.FirstName + ' ' + e.LastName as 'Full Name', s.CompanyName, o.OrderID, o.OrderDate, o.Freight FROM Orders o INNER JOIN Shippers s ON o.ShipVia = s.ShipperID INNER JOIN Employees e ON o.EmployeeID = e.EmployeeID WHERE s.CompanyName = 'Federal Shipping' AND e.FirstName = 'Nancy'
Örnek Sorgu --En cok urun aldigimiz tedarikciyi(Suppliers) almis oldugumuz urun miktarýna gore raporlayin (Sirket Adi - Adet) SELECT s.CompanyName,
110 | S a y f a
SUM(p.UnitsInStock) as 'ToplamAdet' FROM Suppliers s INNER JOIN Products p ON p.SupplierID = s.SupplierID GROUP BY s.CompanyName ORDER BY 2 DESC
Örnek Sorgu --Her bir urunden toplam ne kadarlik satis yapilmis ve urun hangi kategoriye ait (ProductName, CategoryName, ToplamSatis) SELECT p.ProductName, c.CategoryName, ROUND(SUM(od.Quantity * od.UnitPrice*(1-od.Discount)), 2) as 'Toplam Satis' FROM Products p INNER JOIN Categories c ON c.CategoryID = p.CategoryID INNER JOIN [Order Details] od ON od.ProductID = p.ProductID GROUP BY p.ProductName, c.CategoryName
Örnek Sorgu --Tost yapmayı seven çalışanımı getiren sorgu SELECT e.FirstName, e.LastName, e.Notes FROM Employees e Where e.Notes LIKE '%toast%'
111 | S a y f a
Örnek Sorgu --2. Çalışanım hangi çalışanıma bağlı ? (Patron, Personel) + Calisanlarin yasi SELECT calisan.FirstName + ' ' + calisan.LastName as 'Calisan', patron.FirstName + ' ' + patron.LastName as 'Patron' FROM Employees calisan INNER JOIN Employees patron ON calisan.ReportsTo = patron.EmployeeID
Inner Join eşleşen değerleri bana getirir. Yani bir tarafta bir değer, diğer tarafta null var ise bana bu değeri getirmez.
Örnek Sorgu : Outer Join --Hangi Çalışanım hangi çalışanıma bağlı ? (Patron, Personel) + Calisanlarin yasi SELECT calisan.FirstName + ' ' + calisan.LastName as 'Calisan', patron.FirstName + ' ' + patron.LastName as 'Patron', DATEDIFF(YEAR,calisan.BirthDate, GETDATE()) as 'Yas' FROM Employees calisan LEFT JOIN Employees patron ON calisan.ReportsTo = patron.EmployeeID --LEFT OUTER JOIN Employees patron ON calisan.ReportsTo = patron.EmployeeID
OUTER yazmak zorunda değiliz. Left/Right yazmamızda yeterli.
112 | S a y f a
Cross Join : Bütün olasılıkları karşılaştırır. Performans işlemlerinde kullanılır. Örneğin bir siparişler tablosu yaptığımızda , ilk başlangıçta siparişler tablosunda pek bi veri yoktur. Ama zamanla şişebilecek bir tablodur. Siparişler tablosuyla başka bir tabloyu cross yaptığımızda sorgunun performansını ölçebiliriz. Cross join c sharp’da ki iç içe döngü mantığında çalışır. Tüm değerleri birbirleriyle çapraz olarak karşılaştırır. (Çarpım tablosu yapar gibi..)
Örnek Sorgu - CROSS JOIN --Iki tablo arasinda cross baglanti SELECT calisan.FirstName + ' ' + calisan.LastName as 'Calisan', patron.FirstName + ' ' + patron.LastName as 'Patron' FROM Employees calisan CROSS JOIN Employees patron
Employees tablosunda bulunan 8 çalışanı cross olarak birbirleriyle karşılaştırıyor. 8 çalışanın bulunduğu bir tabloda çapraz sorgulama ile 81 satır veri dönüyor. Siparişler tablosu gibi zamanla şişebilecek ve yavaşlayabilecek tablolarda performans sorgusu yapmak için kullanılır.
113 | S a y f a
3.5.4.15. HAVING GROUP BY kullanılan sorgularda where yerine having kullanılır. Having kullandığım da parçalı değerleri where kriterine sokmayı sağlar.
Örnek Sorgu : Yanlış --Toplam satis miktari 1200’un uzerinde olan urunlerin urun adlarini ve satis miktarlarini getiren sorgu SELECT p.ProductName, SUM(od.Quantity) as 'ToplamAdet' FROM [Order Details] od INNER JOIN Products p ON p.ProductID = od.ProductID GROUP BY p.ProductName WHERE (SELECT SUM(o.Quantity) FROM [Order Details] o) > 1200 ORDER BY 2 DESC
Where komutu ile Aggregate Fuction’dan dönen tek bir değeri parçalı hallerini karşılaştırmaya sokamayız. Yukarıdaki satırda, GROUP BY kullanarak ProductName’e göre değerleri parçaladık. Parçalı değerin 1200’den büyük olup olmamasını sorgulamamız gerek. İşin içerisinde GROUP BY varsa HAVING kullanmalıyız. HAVING parçaları değerleri where kriterine sokmayı sağlar.
Örnek Sorgu : Doğru --GROUP BY kullanılan sorgularda where yerine having kullanılır. SELECT p.ProductName, SUM(od.Quantity) as 'ToplamAdet' FROM [Order Details] od INNER JOIN Products p ON p.ProductID = od.ProductID GROUP BY p.ProductName HAVING SUM(od.Quantity) > 1200 ORDER BY 2 DESC
114 | S a y f a
Örnek Sorgu --250'den fazla siparis tasimis kargo firmalarinin adlarini, telefon numaralarini ve tasidiklari siparis sayilarini geriye donduren sorgu SELECT s.CompanyName, s.Phone, COUNT(o.OrderID) as 'TasinanSiparis' FROM Orders o INNER JOIN Shippers s ON o.ShipVia = s.ShipperID GROUP BY s.CompanyName, s.Phone HAVING COUNT(o.OrderID) > 250
3.5.4.16. Zaman Metotları DATEDIFF(YEAR, x.Date, GETDATE()) : İki tarih arasında ki farkı bulur. İlk değeri geriye hangi değeri döndüreceğidir. İkinci değer hangi tarihler arasındaki farkı bulacağıdır.
3.5.4.17. INSERT COMMAND Insert komutu varolan bir kaynağa veri ekleme işlemi için kullanılır. Insert komutunda dikkat edilmesi gereken nokta null geçilemez olan kolonlara insert komutunda yer vermek zorundayız.
Syntax : Insert Insert Into (,,) Values (,,)
Örnek Sorgu --Kategoriler tablosuna yeni bir kayıt ekleme Insert Into Categories (CategoryName,Description) Values ('Yemekler', ’Yediğimiz Pizza’) --Ekleyip eklemediğini kontrol ediyoruz. Select * from Categories
Örnek Sorgu 115 | S a y f a
--Kargocular tablosuna yeni bir kargo firması ekleme işlemi (Shippers) Insert Into Shippers (CompanyName,Phone) Values ('MNG Kargo', '(503) 555-3335') --Kontrol Ediyoruz Select * from Shippers
Önemli : Eğer tüm kolonları sırasıyla biliyorsam, işlemi yaparken kolonlar kısmını yazmayabilirim.Yalnız burada dikkat edilmesi gereken degerleri verirken kolon sıralamasına göre vermektir ve her kolon için değer girmektir.
Örnek Sorgu Insert Into Shippers Values ('Aras Kargo','(503) 444-8598')
NULL değer girmek için değer yerine null yazmalıyız.
Örnek Sorgu --Çalışanlar tablosuna kendimizi kayıt edelim. Insert Into Employees Values ('Kurtbogan', 'Alp', 'Yazılım Uzmanı', 'Dr.', '09.06.1991', '09.06.2012', 'Beykoz', 'İstanbul', '', '542547', 'Turkey', '02458549862', '5485', NULL, '', 3, '')
3.5.4.18. IDENTITY ve SCOPE IDENTITY Sql’de son eklenen kayıtın id’sini elde edebiliriz. ID bilgisine ulaştığımızda her bilgiye ulaşmışız anlamına gelir. Sql’de ID bilgisine ulaşmak bu yüzden bizim için yeterlidir. Yeni bir kayıt ekledikten sonra eklenen kayıtın ID değerine ulaşmamız gerekir.
SCOPE_IDENTITY() : Mevcut oturumda eklenen son kayıtın id’sini döndürür. @@IDENTITY : Global alanda eklenen kayıtın son id’sini döndürür. @@ Sql’de Global alanı temsil eder.
Örnek Sorgu --Son eklenen kayıtın bilgisini elde etmek Insert Into Shippers (CompanyName, Phone) Values ('UPS', '51521512251') Select SCOPE_IDENTITY() –- Mecvut Oturumda Son girilen kaydın ID’sini döndürür.
116 | S a y f a
Select @@IDENTITY -- Scope identity ile aynı işi yapar. Fark başındaki @@ den gelir. @@ sql de global alanı temsil eder.
Örnek Sorgu : Değişkensiz --Siparişler tablosuna yeni bir kayıt ekleyin ve o siparişe bir detay ekleyin.(5. numaralı üründen 10 adet 10 lira üzerinden satış bilgileri içersin) --Değişkensiz Yöntem Insert Into Orders (CustomerID,EmployeeID, OrderDate, RequiredDate, ShippedDate, ShipVia, Freight, ShipName, ShipAddress, ShipCity, ShipRegion, ShipPostalCode, ShipCountry) Values ('ALFKI', 2, '09.09.2013', '09.09.2013','09.09.2013', 2, 25.85, 'SatilanUrunler', 'Beykoz', 'Istanbul', NULL, NULL, 'Turkey') --Urun Detaylarini Eklemek Insert Into [Order Details] (OrderID, ProductID, UnitPrice, Quantity, Discount) Values (SCOPE_IDENTITY(), 10, 95.25, 20, 0.75) Select * from Orders Select * from [Order Details]
3.5.4.19. UPDATE (GÜNCELLE) Tablomuzda hali hazırda bulunan verileri güncellemek için kullanılan sorgudur. Kullanırken dikkatli olmak gerekmektedir. Eğer sorgulama işleminde bir şart belirtilmezse tabloda ki tüm veriler belirtilen değerler ile güncellenecektir. Bu işlemin geri dönüşü yoktur.
Syntax : Update Update Products SET ProductName = '' Where ProductID = --Şart
Örnek Sorgu Update Products SET ProductName = 'Chai ürünü güncellendi' Where ProductID = 1
Yukarıdaki sorgu 1 no’lu id ye sahip ürünün adını “Chai ürünü güncellendi“ olarak değiştirecektir. Sorguyu çalıştırdıktan sonra Select * from Products yazarak sorgu sonucumuzu kontrol ediyoruz.
117 | S a y f a
Sorgumuzda birden fazla değeri update edebiliriz.
Örnek Sorgu Update Products SET ProductName = 'Chai ürünü güncellendi', UnitPrice = 5, UnitsInStock = 200 Where ProductID = 1
3.5.4.20. DELETE Veritabanında bulunan bir veriyi silmek için kullanılır. Update sorgusu gibi kullanılırken çok dikkatli olmak gerekmektedir. Şart belirtilmediğinde, tablodaki tüm verileri siler. Kullanımı Update sorgusu ile aynıdır.
Syntax : Delete DELETE FROM Where =
Örnek Sorgu : Delete DELETE FROM Products Where ProductID = 79
3.5.4.21. DECLARE – DEĞİŞKENLER Sql de değişkenler @ ile tanımlanır global değişkenler @@ ile tanımlanır.
118 | S a y f a
Syntax : Declare Declare @
Örnek Sorgu : Declare Declare @sonid int --sonid yi aşşağıdaki kod a dahil etmeden (seçilmeden) çalıştırırsak hata alırız. Insert Into Orders (CustomerID, EmployeeID, OrderDate, RequiredDate, ShippedDate, ShipVia, Freight, ShipName, ShipAddress, ShipCity, ShipRegion, ShipPostalCode, ShipCountry) Values ('ALFKI', 2, '09.09.2013', '09.09.2013','09.09.2013', 2, 25.85, 'SatilanUrunler', 'Beykoz', 'Istanbul', NULL, NULL, 'Turkey') Set @sonid = SCOPE_IDENTITY() Insert Into [Order Details] (OrderID, ProductID, UnitPrice, Quantity, Discount) Values (@sonid, 10, 95.25, 20, 0.75)
3.5.4.22. VIEWS – SANAL TABLOLAR Bir sorgu içerisinde çok fazla işlem gerçekleştiriyorsak ve bu sorguyu defalarca kullanıyorsak kullanmamız gerekiyorsa bu sorguyu defalarca yazmak yerine sql Serverin bize sunmus oldugu nesne olan view nesnelerini kullanılırız. View aynı zamanda güvenlikde sağlar.
Syntax : Views Creat VIEW AS
View Yazarken kolon adlarını yazmamız gerekir.* ile tüm kolonları yazdırmaya çalışırsak aynı kolonlar olacağından (uniq kolonlar) hata verecektir.
Örnek Sorgu : Views --Dumon id sine sahip müşterinin almış oldugu siparişlerin siparisID, SiparisTarihi, MusteriId ve SirketAdi Create View vw_DumonSiparisleri AS Select o.OrderID, o.OrderDate, c.CustomerID, c.CompanyName From Orders o Inner Join Customers c On c.CustomerID = o.CustomerID Where c.CustomerID = 'DUMON'
119 | S a y f a
--Sanal Tabloyu gerçek bir tabloymuş gibi kullanabiliriz. Select * From vw_DumonSiparisleri d Where d.OrderID > '10650'
Örnek Sorgu : Views --Speedy Express ile taşınmış, nancy nin almis oldugu, DUMON yada ALFKI id li müsteriler tarafından verilmiş olan siparisleri saklayan view olusturunuz. --Shippers, Customers, Employees, Orders CREATE View vw_SpeedyIleTasinmis As Select s.CompanyName as 'ShipperCompanyName', e.FirstName + ' ' + e.LastName as 'SiparisAlan', c.CustomerID, c.CompanyName as 'CustomerCompanyName' From Orders o Inner Join Shippers s on s.ShipperID = o.ShipVia Inner Join Customers c on c.CustomerID = o.CustomerID Inner Join Employees e on e.EmployeeID = o.EmployeeID Where (s.CompanyName = 'Speedy Express') and (e.FirstName = 'Nancy') and (c.CustomerID = 'DUMON' or c.CustomerID = 'ALFKI')
Sorguyu güncellerken CREATE yerine ALTER kullanılır. CREATE yeni bir view oluştururken kullanılır.
Bir sorguyu güncellemek için CREATE yerine ALTER kullanılır.
Örnek Sorgu : View Silmek DROP VIEW vw_SpeedyIleTasinmis -- Bu sorgu çalıştıgında olusan view sorgusunu silecektir.
Örnek Sorgu : Views --Ortalama satış miktarının (para bazlı) üzerine çıkan satışlarım nelerdir. (Viewli) --(Orders details) GO Create view vw_DetaySorgusu AS Select od.OrderID, ROUND(SUM(od.UnitPrice * od.Quantity *(1-od.Discount)),2) as 'ToplamTutar' From [Order Details] od Group by od.OrderID Having SUM(od.UnitPrice * od.Quantity *(1-od.Discount)) > (Select AVG(t.SiparisBazliPara) as 'Toplam' From ( Select
120 | S a y f a
od.OrderID as 'SiparisID', SUM(od.UnitPrice * od.Quantity *(1-od.Discount)) as 'SiparisBazliPara' From [Order Details] od Group by od.OrderID ) as T)
3.5.4.23. WITH ENCRPYTION Oluşturduğumuz view’ları şifreli view olarak oluşturabiliriz. View’a sağ tıklayıp ‘Desing’ seçeneğini seçtiğimizde, view kodlarını ve içeriklerini görebiliriz. With Encryption bu opsiyonu kaldırır. Tüm database nesnelerine uygulanabilir.
Örnek Sorgu : Database Nesnelerini Şifreleme CREATE View vw_SpeedyIleTasinmisSifreli WITH ENCRYPTION --(bu satırı ekleyerek sifreli oluşturabiliriz. Düzenleme için Create yerine alter yazmalıyız.) As Select s.CompanyName as 'ShipperCompanyName', e.FirstName + ' ' + e.LastName as 'SiparisAlan', c.CustomerID, c.CompanyName as 'CustomerCompanyName' From Orders o Inner Join Shippers s on s.ShipperID = o.ShipVia Inner Join Customers c on c.CustomerID = o.CustomerID Inner Join Employees e on e.EmployeeID = o.EmployeeID Where (s.CompanyName = 'Speedy Express') and (e.FirstName = 'Nancy') and (c.CustomerID = 'DUMON' or c.CustomerID = 'ALFKI')
3.5.4.24. VIEW ile INSERT – Sanal Tabloları Kullanarak Insert İşlemi Bir view üzerinden tabloya insert yapılmak istenirse.. sorgunun birden fazla tablodan (inner join), group by ve benzeri yapıların olmaması gerek. Boş geçilemeyen kolon view’da yoksa o view üzerinden insert gerekleştirilemez.
Örnek Sorgu : View ile Insert --SanalTabloya insert etmek.. (zorunlu kolonlara değer vermediğimizde hata verir. Örn CategoryName) Create View vw_KatDesc As Select c.CategoryName, c.Description From Categories c GO --SanalTabloya insert etmek.. (zorunlu kolonlara değer vermediğimizde hata verir. Örn CategoryName) Insert into vw_KatDesc
Örnek Sorgu --Calisanlar tablosuna view olustur ve o tablo üzerinden bir kayıt ekle.. ALTER View vw_CalisanlaraKayitEkle AS Select e.FirstName, e.LastName From Employees e GO Insert into vw_CalisanlaraKayitEkle (FirstName,LastName) Values ('Alp', 'Kurt') GO Select * from vw_CalisanlaraKayitEkle GO
3.5.4.25. FQN – Fully Qualified Name FQN dediğimiz yapı; tam isim anlamına gelir. Biz bir sorgu çekerken aslında bu tam ismi kullanarak sorgularımızı çekmeliyiz.
FQN Yapısı [ServerName].[DatabaseName].[SchemaName].[ObjectName] --Database de ki nesnelere tam isim ile ulaşılır. Sıralaması önemlidir.(aşşağıdaki gibi) --DBO : Database Owner (Database Sahibi) --ObjectName nesnedir. VIEW de bir objedir. SELECT * FROM sys.servers –-Bu satır ile ServerName’e ulasabiliriz. SELECT * FROM [ALP1-BILGISAYAR\EMPATI].Northwind.dbo.Categories
3.5.4.26. STORED PROCEDURE – SAKLI YORDAM İkili iletişim sağlayabilen (ben parametre vericem o bana sonuc getiricek) InsertUpdate-Select-Delete kullanılabilir. Güvenli yapılardır. Veritabanımızın içindeki Programmability içerisindeki stored procedure içinde bulunurlar.
122 | S a y f a
Stored Procedure’ler güvenli yapılardır. Güvenli yapılar Database Altında > Programmabilty içerisinde bulunurlar. Güvenli oldukları için çalışmaları daha hızlıdır. Güvenli yapılar oldukları için bir Security kısmından geçmezler. Performans olarakda biraz daha hızlıdırlar.
Syntax --Create PROC olarakda kullanılabilir. Create procedure (--Parametre istiyosak istediğimiz kadar parametre isteyebiliriz. @ @ @ ) As
Örnek Sorgu --Dışarıdan girilen kategori adı ve açıklamaya göre kategoriler tablosuna insert işlemi yapan prosedür. GO Create PROC prc_KategoriEkle ( @katAdi nvarchar(50), @aciklama nvarchar(MAX) ) AS Insert Into Categories (CategoryName, Description) Values (@katAdi, @aciklama) --Verileri eklemek için aşşağıdaki satır kullanılır. EXECUTE prc_KategoriEkle 'Kategori1', 'Aciklama1' --Ekleme insert ile değil Execute ile yapılır. Exec olarakta yazılabilir. --Ekleme işleminden sonra tabloya insert yapıldıgı için tabloyu çağırabiliriz. Select * From Categories
Örnek Sorgu --Shippers tablosunda UPDATE işlemi yapabilen bir sp olusturunuz. GO ALTER PROC prc_ShipperGuncelle ( @guncellenecek nvarchar(50), @companyname nvarchar(50), @phonenumber nvarchar(50) ) AS UPDATE Shippers
123 | S a y f a
Set CompanyName = @companyname, Phone = @phonenumber Where CompanyName = @guncellenecek GO EXEC prc_ShipperGuncelle 'MNG Kargo', 'Yurtici Kargo', '(222) 444-5522'
Örnek Sorgu --Shippers tablosunda DELETE işlemi yapabilen bir sp olusturunuz. GO ALTER PROC prc_ShipperSil ( @id int ) AS Delete from Shippers where ShipperID = @id EXEC prc_ShipperSil 18
Örnek Sorgu --Shippers tablosunda INSERT işlemi yapabilen bir sp olusturunuz. GO Create PROC prc_ShipperEkle ( @companyname nvarchar(50), @phonenumber nvarchar(50) ) AS Insert INTO Shippers Values (@companyname,@phonenumber) GO EXEC prc_ShipperEkle 'MGN Kargo', '(555) 123-4466'
Örnek Sorgu --Dışarıdan girilen miktara göre tüm ürünlere zam yapan prosedür. GO Create PROC prc_ZamYap ( @miktar money ) AS UPDATE Products Set UnitPrice += @miktar GO --Çalıştırmak için alt satırdaki kodları kullanılırız. EXECUTE prc_ZamYap 5 GO
Örnek Sorgu --Disaridan girilen kategori adına göre ürünleri listeleyen prosedür. Create PROC prc_KategoriListele ( @KategoriAdi nvarchar(50)
124 | S a y f a
) AS Select * From Products p Inner Join Categories c On c.CategoryID = p.CategoryID Where CategoryName = @KategoriAdi GO Execute prc_KategoriListele 'Beverages' GO
Örnek Sorgu --Stok miktarı dışarıdan girilen iki değer arasında olan ürün fiyatı yine disaridan girilen 2 deger arasında olan, toptanci firma(suppliers) adi disaridan girilen degeri barındıran urunlerin, urunadlarini,fiyatlarini,kdv eklenmis fiyatlarimi, stoktaki miktarini ve toptanci firma adlarini getiren prosedür... --Products, supplier, --Dışarıdan girilcek değerler (stok miktarları, fiyatları, toptanci firma adi, --ürünadı, fiyatı, kdv eklenmis fiyatı, stoktaki miktarını ve topranci firma adı GO ALTER PROC prc_StokGosterimi ( @minStok int, @maxStok int, @minFiyat int, @maxFiyat int, @SupplierName nvarchar(50) ) AS Select p.ProductName, p.UnitPrice, p.UnitPrice * 1.18 as 'KdvliFiyat', p.UnitsInStock, s.CompanyName From Products p INNER join Suppliers s On s.SupplierID = p.SupplierID WHERE (p.UnitsInStock > @minStok and p.UnitsInStock < @maxStok) and (p.UnitPrice>@minFiyat and p.UnitPrice < @maxFiyat) and (s.CompanyName LIKE '%'+@SupplierName+'%') GO Exec prc_StokGosterimi 20,50,20,50,'Pasta'
3.5.4.27. IF ELSE – Karar Yapıları Sql tarafındaki karar yapılarıdır. IF içerisinde verilen sorgudan dönen sonuç (etkilenen satır sayısı) 0’dan büyükse True, 0’a eşitse False değer döndürür. C# tarafındaki scope’lar yerine Begin End Kullanılır. Bu taraftaki if verinin database’de olup olmadığını sorgulamak için yapılır.
Syntax 125 | S a y f a
IF() Begin End Else Begin End
Örnek Sorgu --Kargo Şirketlerimde Yurtici kargo diye bir şirket varsa telefon numarası (222) 111-2233 seklinde güncellensin. Eğer böyle bir kayıt yoksa kayıt bulunamamaktadır mesajı çıksın. PRINT 'Merhaba Dünya' --Messages alanına mesaj yazdırmak için kullanılır. IF EXISTS (Select * from Shippers s Where CompanyName='Aras Kargo') BEGIN Update Shippers Set Phone = '(222) 111-2244' Where CompanyName='Aras Kargo' END ELSE BEGIN PRINT 'Kayıtlı Değil' END GO
Örnek Sorgu --Ürünler tablosuna kategorisi yemekler olan bir ürün eklenecek ve ardindan o urun için 10248 orderidli bir ürün detayi olusturulacak Eğer ürünün kategorisi veritabanında mevcut ise işlem gercekleştirilecek mevcut değilse bu iki işlem gerçekleştirilmeyecek USE Northwind IF NOT EXISTS (Select * from Categories where CategoryName = 'Yemekler') BEGIN Insert INTO [Order Details] (OrderID, ProductID, UnitPrice, Quantity,Discount) VALUES (10248, 41, 20, 25,0) END ELSE BEGIN PRINT 'Hata' END GO
3.5.4.28. DÖNGÜLER Sql’de sadece While döngüsü bulunmaktadır.
Syntax WHILE () BEGIN
126 | S a y f a
END
Örnek Sorgu --1 den 10 a kadar sayıları kendi oluşturdugumuz tabloya atmak. DECLARE @tablom TABLE ( Sayi int ) DECLARE @sayac int SET @sayac = 1 While(@sayac < 20) BEGIN Insert Into @tablom (Sayi) Values (@sayac) Set @sayac +=1 END --Tabloyu göstermem gerek Select * from @tablom --Bunu yazarken üstteki declare tablom satırını eklememiz gerekir.
3.5.4.29. FUNCTION YAPISI Fonksiyon yapısı bir database nesnesidir. Kullanıcı ile iletişime geçebilen bir yapıdır. Stored Procedure gibidir. Ama tek farkı tablodan bağımsızdır.
Funtion’ların Yapısı – Sql’de Tanımlı Function SELECT GETDATE() SELECT DATEDIFF(YEAR, '06.09.1991', '12.25.2014')
--Bir takım işlerden bize bir dizi değer döndüren nesnelerdir. --Fonksiyon içerisinde insert update delete gibi işlemler
Syntax CREATE Function ( , , , ) RETURNS AS BEGIN return END
127 | S a y f a
Örnek Sorgu GO ALTER Function fnc_Toplama ( @sayi1 int, @sayi2 int ) RETURNS int AS BEGIN RETURN @sayi1+@sayi2 END GO --Kullanımı Select dbo.fnc_Toplama(5,10) Select p.ProductName, p.UnitPrice, ROUND(dbo.fnc_Toplama(UnitPrice,5),2) as 'ZamliFiyat' from Products p
Örnek Sorgu --Girilen tarihe före yas hesaplayan fonksiyon GO ALTER Function fnc_yashesapla ( @yas date ) RETURNs int As BEGIN Return DateDiff(YEAR,@yas,GETDATE()) END GO --Tablodan Bağımsız Kullanım Select dbo.fnc_yashesapla('01.01.1991') --Tablodan veri çekerek kullanım Select e.FirstName + ' ' + e.LastName as 'FullName', dbo.fnc_yashesapla(e.BirthDate) as 'Yas' From Employees e
Örnek Sorgu --Girilen isim soyisim ve şirket adına göre bir mail adresi olusturan fonksiyon GO ALTER function fnc_EmailOlustur ( @isim nvarchar(50), @soyisim nvarchar(50), @sirketadi nvarchar(50)
128 | S a y f a
) Returns nvarchar(50) As BEGIN return LOWER(@isim + '.' + @soyisim + '@' + @sirketadi + '.com') END GO Select dbo.fnc_EmailOlustur('Alp', 'Kurtbogan','Bilgeadam') --Tabloda Kullanmak Select e.FirstName, e.LastName, dbo.fnc_EmailOlustur(e.FirstName, e.LastName, 'SirketAdi') From Employees e
3.5.4.30. TRIGGER - TETİKLEYİCİ Database üzerinde bir işlem yapıldıgında otomatik olarak arka planda başka bir işlemin yapılmasını sağlayan veritabanı nesnesidir. İki durum için kullanılabilir. After : Sonra Instead Of : Yerine
Syntax Create TRIGGER ON --Oncemi sonramı olayına 2 farklı durum kullanabiliriz. After ve instead of(yerine) As
Örnek Sorgu --Siparis detayları tablosuna bir kayıt eklendiğinde otomatik olarak girişi yapılan siparis detayının stoktaki miktardanda düşülmesini sağlayan trigger GO Create TRIGGER trg_StokGuncelle ON [Order Details] AFTER INSERT As Declare @proid int, @adet int Select @proid = ProductID, @adet = Quantity from inserted UPDATE Products Set UnitsInStock -= @adet Where ProductID = @proid GO
Örnek Sorgu --Urunlerin tablosunda bir kayit silmeye calistigimizda urunu silmek yerine discountinued degerini 1 yapan trigger
129 | S a y f a
GO Create TRIGGER trg_Guncelleme On Products Instead Of Delete AS DECLARE @id int Select @id = ProductID from deleted Update Products Set Discontinued = 1 where ProductID = @id Delete from Products where ProductID = 2 Select * from Products GO
Örnek Sorgu --Kategoriler tablosundaki 10 nolu kaydı koruma altına alan triger.. GO ALTER Trigger trg_KategoriKoru On Categories Instead Of Delete As Declare @id int Select @id = CategoryID from deleted IF(@id = 10) BEGIN PRINT 'Silemezsin :)' END ELSE BEGIN Delete from Categories where CategoryID = @id END GO --Silme İşlemi Delete from Categories where CategoryID = 10 --Kontrolü Select * from Categories
Örnek Sorgu --Database e yeni tablo ekletmeyen trigger GO Create TRIGGER trg_DirenTablo On DATABASE FOR Create_Table --For dan sonra bir kelimelik hakkımız var alt tre ile yazmalıyız. AS PRINT 'Yeni tablo oluşturamazsınız. İmza : direntablo' ROLLBACK --Geri Sar GO Create Table Deneme2 ( Kolon1 nvarchar(50) )
130 | S a y f a
3.5.4.31. TRANSACTION Transaction ya hep ya hiç mantıgında çalışır. Try catch entegre çalışan bir yapıdır.
Syntax BEGIN TRY BEGIN TRAN COMMIT TRAN END TRY BEGIN CATCH ROLLBACK TRAN END CATCH
Örnek Sorgu --2 idli musteriden 1000 tl dusup 1 nolu id ye sahip musteriye 1000 tl eklemek. Bunu güvenlik altına almak. USE BankaDb BEGIN TRY BEGIN TRAN trn Update Musteriler Set Bakiye -= 1000 Where id = 2 ------RAISERROR('Hata', 16,1) --Hata patlatırsak ----Update Musteriler Set Bakiye += 1000 Where id = 1 PRINT 'Islem Basariyla Gerceklesti.' COMMIT TRAN END TRY BEGIN CATCH ROLLBACK TRAN trn SELECT ERROR_MESSAGE() as 'Hata Mesaji', ERROR_LINE() as 'Hata Satiri', ERROR_NUMBER() as 'Hata Numarasi' END CATCH Select * from Musteriler
Örnek Sorgu --Ürünler tablosuna kategorisi yemekler olan bir ürün eklenecek ve ardindan o urun için 10248
131 | S a y f a
orderidli bir ürün detayi olusturulacak Eğer ürünün kategorisi veritabanında mevcut ise işlem gercekleştirilecek mevcut değilse bu iki işlem gerçekleştirilmeyecek USE Northwind IF NOT EXISTS (Select * from Categories where CategoryName = 'Yemekler') BEGIN Insert INTO [Order Details] (OrderID, ProductID, UnitPrice, Quantity,Discount) VALUES (10248, 41, 20, 25,0) END ELSE BEGIN PRINT 'Hata' END GO --TRANSACTION YONTEMİ BEGIN TRY BEGIN TRAN trn2 IF NOT EXISTS (Select * from Categories where CategoryName = 'Yemekler') BEGIN Insert Into Products (ProductName, ) Insert INTO [Order Details] (OrderID, ProductID, UnitPrice, Quantity,Discount) VALUES (10248, 41, 20, 25,0) END ELSE BEGIN RAISERROR('Hata', 16,1) END COMMIT TRAN trn2 END TRY BEGIN CATCH ROLLBACK TRAN trn SELECT ERROR_MESSAGE() as 'Hata Mesaji', ERROR_LINE() as 'Hata Satiri', ERROR_NUMBER() as 'Hata Numarasi' END CATCH
3.5.4.32. SQL’de PERFORMANS Yazılımcılar, SQL’de performansdan’da sorumludur. Tablo çok şiştiğinde tabloda arama yapmak zorlaşmaya başlıyor yani sorgu sonucunu almak zorlaşıyor. Ama Sql Server’da çok güzel bir yöntem söz konusudur.
INDEX’lerde birer veritabanı nesneleridir. Indexlerin mantığı; bir kitapda içerikler sayfası yada kitap sonunda index sayfasının olması gibi düşünebiliriz. Bu bilgi sayfalarında kitap içerisinde geçen kelimelerin hangi sayfada olduğunu bulabiliriz.
132 | S a y f a
SQL Server da biraz daha detaylı bir mantık söz konusudur. Biz bir tablo oluşturup veriler girmeye başladığımızda PK (Primary Key) attığımız kolon bir index kolonu olur. Indexler ikiye ayrılır Clustered Index ve Non-Clustered Index, bu ayrım indexlenen yapının ne olduğu ile ilgilidir. Birinde datalar indexlenir, diğerinde sadece referansları indexlenir.
3.5.4.33. INDEX YAPISI Index’ler SQL’de performansdan sorumlu nesnelerdir. 2’ye ayrılırlar. Clustered Index (PK Kolonuna uygulanır.) Bir tabloda yanlızca bir tane olabilir. Sayfa seviyesinde verinin kendisi tutulur. Non-Clustered Index Genel olarak WHERE, Order By ve Group By sorgularında sık kullanılan kolonlar için uygulanır. Sayfa seviyesinde datanın referansı (yani adresi) tutulur.
3.5.4.33.1.
CLUSTERED INDEX
Bir tabloda PK kolonu yaptığımızda o kolona göre bir indexleme yapılır. Dataların kendisi indexlenir. Root Level () Non-Leaf Level (Sayfa Olmayan Seviye) Leaf Level (Sayfa Seviyesi)
3.5.4.33.2.
NON-CLUSTERED INDEX
Clustered index’I biz oluşturamayız. Ama Non-Clustered index oluşturabiliriz.
133 | S a y f a
Syntax CREATE NONCLUSTERED INDEX ON (
Örnek Sorgu CREATE NONCLUSTERED INDEX ind_PostalCode ON Customers(PostalCode)
Oluşturduğumuz index, tablomuzun altında Indexes içerisinde bulabiliriz.
Design alanından’da index oluşturabiliriz. Design sekmesine gidip, kolon seçtikten sonra Indexes and Keys seçeneği seçilir. Var olan tablo üzerindeki indexleri gösterir. Add dediğimizde yeni bir tane ekler. Name : Index Adı Column : Hangi Kolona göre Fill Specificitions : Fill Factor sayfanın doluluk oranına göre sayfalar. Life level yapısına göre. (Sayfanın doluluk oranı kullanımına göre değişir.)
3.5.4.33.3.
Index Durumunu Sorgulama
Veritabanında bulunan indexler bir süre sonra bozulabilir. Performansı olumsuz etkilediğinde, indexleri tekrardan oluşturmam gerekir. Index durumlarını sorgulamak için aşağıdaki komutu kullanabiliriz.
Index Durumunu Sorgulama 134 | S a y f a
DBCC SHOWCONTIG
Yukarıdaki sorguyu çalıştırdığımızda seçili olan veritabanının tablolarının index durumları rapor olarak listelenir.
Yukarıdaki raporda en çok dikkat etmem gerekenler; Paged Scanned : Veriler kaç sayfada bulunuyor. Scan Density : Taranabilme sayısı / Tarama Sayısı olarak algılanır. Yani örneğin; verileri 10 sayfada tarayabilirdin, ama 15 sayfada taradın gibi bir sonuç çıkarabiliriz. Bu da indexlerin yavaş yavaş bozulmaya başladığını bize gösterir ve indexleri yeniden düzenlememiz gerekmektedir. Logical Scan Fragmentation : Bozulma yüzdesi anlamına gelir. Bozulma %10 üzerindeyse indexleri yeniden düzenlememiz gerekmektedir.
ShowContig yapısını özelleştirebiliriz. Tüm veritabanı yerine sadece belirttiğimiz tabloda tarama yapabiliriz.
Tek Bir Tabloda Tarama Yapmak DBCC SHOWCONTIG([Order Details])
Yukarıdaki sorguyu çalıştırdığımızda tablomuz ile ilgili değerler görünecektir.
135 | S a y f a
Yukarıda sunulan raporda Scan Density’de gördüğümüz [2:5] ifadesi, bu tablodaki tarama 2 sayfada yapılabilecek durumdayken, 5 sayfada yapılmış anlamına gelir. Bu ifade benim index yapımın bozulduğunu gösterir. Locigal Scan Fragmentation’da 20% bir bozulma olduğu görülüyor.
Tablomuzdaki index yapısını düzenlemek için aşağıdaki komutu kullanabiliriz.
Syntax DBCC DBREINDEX ('', '', '')
Yukarıdaki komutu kullanarak tablomuzdaki indexlemeyi yeniden yapabiliriz. Index adi alanını boş bıraktığımda tüm indexler yenilenecektir.
Örnek DBCC DBREINDEX('Order Details', '', 90)
Yukarıdaki mesaj ile karşılaştığınızda, indexleme işlemi başarıyla gerçekleştirilmiş anlamına gelir. Şimdi tekrar index yapımızı kontrol edelim.
DBCC SHOWCONTIG([Order Details])
Ve sonuç aşağıdaki resimde olduğu gibidir.
136 | S a y f a
3.5.4.34. Görev Tanımlama Sql Agent kullanarak yukarıdaki işlemi görev olarak atayabiliriz. Sql Server sürümünüz uygunsa, Management > Maintenance Sağ tıklayıp > New Maintenance Plan seçeneği ile yeni bir plan oluşturabilirsiniz.
Açılan pencerede çalışacak sorgular için zamanlar belirleyebiliriz. Belirli saatlerde çalışacak sorgular atayarak bu işlemi gerçekleştirebiliriz.
Verilen tablodaki Index bilgilerini döndüren sistemde bulunan bir Stored Procedure bulunmaktadır. Bu komutu kullanarak hızlı ve kolay bir şekilde index bilgilerine ulaşabiliriz.
Örnek EXEC sp_helpindex 'Employees'
Not : “EXEC sp_” yazıldığında gelen stored procedure’ler sistemden gelen sp’lerdir.
3.5.4.35. Kullanıcı Oluşturma ve Rol Belirleme Security penceresinde bulunan Logins klasörüne sağ tıklayıp New Login diyerek yeni bir kullanıcı tanımlayabiliriz.
137 | S a y f a
Yeni Login oluşturma ekranında kullanıcımız ile ilgili temel bilgileri veriyoruz. Kullanıcı adı, authentication bilgisi ve varsayılan olarak gelen seçili veritabanını seçiyoruz.
Server Roles penceresi kullanıcımızın veritabanları üzerindeki yetkisini belirlemek için kullandığımız sekmedir. Server’da tanımlı olan sabit roller vardır. Oluşturulan kullanıcı bir role dahil edilir. Kullanıcı oluşturulur oluşturulmaz public rolüne dahil edilir. Public rolünün bir yetkisi yoktur.
138 | S a y f a
User Mapping -> oluşturulan kullanıcının hangi veritabanlarına girilebileceği bilgisi verilir. Seçili veritabanındaki belirtli rolleri yönetebiliriz. Bu alana rol tanımlanıp kendi oluşturduğumuz rolüde kullanabiliriz.
Server’a login olacak kişinin Server Rolünü sysadmin yapıldığında, verilen kısıtlamaların bir anlamı yoktur. Sysadmin herşeyin üzerine çıkar ve kısıtlama yapılamaz.
Status penceresinde ise kullanıcıyı Enable veya Disable edebiliriz.
Ado.Net Veri tabanı işlemleri için kullanacağımız yapıdır. Veri çekme, ekleme, güncelleme ve silme işlemlerini yapabilmemize olanak sağlar.
139 | S a y f a
Veri Çekme İşlemi için aşağıda ki adımlar gerçekleştirilir. 1. 2. 3. 4. 5.
Bağlantıyı oluştur. Sorguyu oluştur. Bağlantıyı aç. Sorguyu çalıştır. (Veriyi elde et veya gönder) Bağlantıyı kapat.
Ado.net ‘in çalışabilmesi için Sql Server Managament Studio ‘nun açık olmasına gerek yoktur. Yanlızca Sql girişinin (Servisinin çalışır durumda olması) açık olması yeterlidir.
4.1. Veritabanı Bağlantı Yöntemleri 4.1.1. SqlConnection SqlConnection nesnesi veritabanı işlemlerimizi gerçekleştirmek için kullanacağımız nesnemizdir. System.Data.SqlClient kütüphanesi altında bulunur. Görevi, bizim Sql sorgularımızı çalıştırmak için gereken veritabanı bağlantısını kurmaktır.
Temel görevi, görsel olarak düşündüğümüzde bize MsSql ekranındaki Query sayfasını açmaktır. Bizden beklediği Server Name, Database Name, Username, Password bilgileri ile Sql servisine bağlanarak sorguları çalıştırabileceğimiz bağlantıyı oluşturur. Sorguların çalışması için MsSQL Server’in açık olmasına gerek yoktur. Sql’e girişin yani servisin açık olması yeterlidir.
SqlConnection; Arkatarafta temel mantıkta yapılan işlem, Sql Management Studio’yu açar, giriş yapar, veritabanını seçer, new query ekranı açar.
4.1.2. Kütüphaneler 4.1.2.1. System.Data.Common Veriye erişim kaynaklarında kullanılan sistemlere yönelik bir yapıdır. 4.1.2.2. System.Data.Odbc Open Database Connectivity mantığına uygun yapıları içerir. Open Database Connectivity standartlarına uygun yapıları içerir. 4.1.2.3. System.Data.Sql ve System.Data.SqlClient Sql’e özelleşmiş yapılardır. 4.1.2.4. System.Data.Oledb Her türlü veritanına erişmek için kullanılan ana yapıdır. Sql Client bu yapının özelleşmiş halidir. OleDb’de Connection nesnesi bulunur. Özelleşmiş yapılar (SqlClient, OracleClient, MySqlClient gibi) Oledb’den türemiştir. Burda OracleClient bulunmadığından, OracleClient kütüphanesini internetten bulup projeye dahil ettiğimizde diğer veritabanlarınıda kullanabiliriz.
140 | S a y f a
4.1.2.5. System.Data.ProviderBase Kendi bağlantımı oluşturmam için bana yapılar sunar. Ürettiğimiz bir database yapısı olursa bu namespace’den tanımlama yapılır. 4.1.2.6. System.Data.SqlTypes Sqlde tanımlı olan, c sharp da tanımlı olmayan yapıları c sharp tarafında birebir kullanmak için tanımlı olan yapıdır. (money gibi..)
4.1.4. AppConfig dosyası içerisinde ConnectionString Kullanmak
Namespace’lere System.Configuration dosyasını eklememiz gerekir. System.Configuration kütüphanesi, bizim configuration dosyamızı yönetmemizi sağlar. Kütüphaneyi referanslara eklemek için; References Sağ Tık > Add Reference Arama alanına Configuration yazdığımızda çıkan System.Configuration’ı eklememiz gerekmektedir.
141 | S a y f a
Yöntem 5 : ConnectionString’i ConfigurationFile’dan Çekmek ConnectionString SqlConnection baglan = new SqlConnection(ConfigurationManager.ConnectionStrings["Baglan"].ConnectionString);
4.2. CONNECTED MİMARİ
Ado bağlantılıdır. Bu yapıda SQL’e bağlantıyı kendimiz yönetiriz. Bağlantıyı açmak ve kapatmak yazılımcı tarafından yönetilir.
if (baglan.State == ConnectionState.Closed) //Bağlantı kapalıysa, sonuç True Döner.. { baglan.Open(); //Bağlantıyı Açan metot. MessageBox.Show("Bağlantı Açıldı!"); } else { baglan.Close(); //Bağlantıyı Kapatan metot baglan.Dispose(); //Bağlantıyı RAM'den düşürür. MessageBox.Show("Bağlantı Kapandı"); }
ConnectionState: Bize bağlantının durumunu true ve false olarak geri dönecektir.
4.2.2. SqlCommand Şu ana kadar sadece veritabanı bağlantısını oluşturduk. Bağlantıları açtık veya kapattık. Ama henüz veritabanı ile ilgili işlem yapmadık. Artık bağlantılarımızı açtıktan sonra Sql sorgularını çalıştırmaya başlayabiliriz. Bu işlem için SqlCommand nesnesini kullanabiliriz.
SQL taraflı olarak bir sorgu çalıştırmak isterseniz referans alacağınız nesne "SqlCommand" nesnesidir.
142 | S a y f a
4.2.2.1. SqlCommand Property(Özellikleri) Connection : Çalıştırılacak sql cümlesinin, hangi veritabanı bağlantısını kullanacağını gösterir. CommandType : Çalıştırılacak sql cümlesinin tipini belirler. Query, StoredProcedure, TableDirect değerlerini alır. Query : Sql cümlesinin çıplak olarak kullanıldığı özellik StoredProcedure : Sql cümlesinin Stored Procedure olarak kullanıldığı özellik TableDirect : Sql cümlesi yerine direk olarak tablo ismi verilerek kullanıldığı özellik. (Birden fazla tablo kullanılacak ise, tablo isimleri , işareti ile ayrılır. )
CommandText : CommandType özelliği göz önünde bulundurularak sql cümlesi, stored procedure veya tablo isminin yazıldığı özelik. CommandTimeout : Sql cümlesinin çalıştırılması ve cevap dönme süresi için bekleme zamanını belirtir. Varsayılan değeri 30’dur. Süre saniye cinsinden verilir. Transaction : Çalıştırılan sql cümlesine, oluşturulan transaction nesnesi bağlanılarak, ADO.NET düzeyinde kontrol yapılması sağlanabilir. Bu uygulamanın bize sağladığı fayda, çalıştırılan sql cümlesinin, çalıştırılması sonucu oluşan hatalarda geriye dönüş yapılabilmesine imkan vermesidir. Çoğunlukla, Insert/Update/Delete işlemlerinde kullanılır. Parameter : SqlCommand nesnesi aracılığı ile çalıştırılan Sorgulara ve Stored Procedure’lere tanımlanan parametrelere değer göndermek için kullanılır.
1.Yöntem : Query String SqlCommand cmd = new SqlCommand("Select * from Categories", baglan);
Tam Yapı SqlConnection baglan = new PWD=123"); //Bağlantı nesnemiz
SqlConnection("Server=.;
Database=Northwind;
UID=sa;
SqlCommand cmd = new SqlCommand("Insert Into Categories (CategoryName, Description) VALUES ('Yeni Kategori', 'Açıklaması')", baglan); //baglan nesnesini kullanarak kategoriler tablosuna insert yapan sorguyu verdik. if (baglan.State == ConnectionState.Closed) baglan.Open(); //Bağlantıyı açar. Int etkilenen = cmd.ExecuteNonQuery(); //Etkilenen kayıt sayısını döner baglan.Close(); //Bağlantıyı kapattık baglan.Dispose(); //RAM'den düşürdük
4.2.2.2. SqlCommand Metotları ExecuteNonQuery : Etkilenen satır sayısını geriye döndürür. ExecuteScalar : Result set’in birinci sutununun birinci satırını geri döndürür.
143 | S a y f a
ResultSet : Select * from dediğimizde dönen tablodur.
ExecuteReader : ResultSet’in tamamını geriye döndürür.
Execute metotlarından bana dönen değeri kullanabilirim. Örneğin ExecuteNonQuery() bana etkilenen satır sayısını döndürür. Ben bu sayıyı kontrol ederek ekleme işleminin gerçekleşip gerçekleşmediğine bakabilirim.
Execute Nesnesinden Dönen Değerin Kontrolü 1.Yöntem int etkilenenSatirSayisi = cmd.ExecuteNonQuery(); //Etkilenen satır sayısını elde ederiz. 2.Yöntem bool sonuc = cmd.ExecuteNonQuery() > 0; //Etkilenen satır sayısı 0'dan büyükse true değer döner. Buda işlemin başarıyla gerçekleştiğini gösterir.
Insert İşlemi Yapmak //Dışardan girilen kategori adı ve açıklamasına insert yapan kodlar SqlConnection baglan = new SqlConnection("Server=.; Database=Northwind; UID=sa; PWD=123"); SqlCommand cmd = new SqlCommand("Insert Into Categories (CategoryName, Description) VALUES ('" + txtKategoriAdi.Text + "', '" + txtAciklama.Text + "')", baglan); if (baglan.State == ConnectionState.Closed) baglan.Open(); bool sonuc = cmd.ExecuteNonQuery() > 0; //Etkilenen satır sayısı 0'dan büyükse değişkene true değer atar. if(sonuc) //Eğer etkilenen satır sayısı 0'dan büyükse true döner MessageBox.Show("Kategori başarıyla kayıt edildi."); else MessageBox.Show("Kategori kayıt edilirken bir hata oluştu."); baglan.Close(); baglan.Dispose();
4.3. DISCONNECTED MİMARİ
Disconnected Mimari; sql sorgularımızı çalıştırmak için oluşturduğumuz bağlantıyı açma/kapama işlemini üstlenir. Disconnected mimaride bağlantıları yapının kendisi yönetir.
Bunun dışında disconnected mimaride veri çekme hızı connected mimariden daha yüksektir. Connected mimari ile dönen ResultSet’i satır satır okumak durumundayız. Ama disconnected mimari, veri okuma işlemleri için kullanılan hazır yapıları kullanarak daha hızlı bir şekilde verileri çeker.
Veri çekme işlemi arasında ki hız farkını Entity Framework’de inceleyeceğiz. Şimdi Disconnected Mimaride kullanılan yapıları inceleyelim.
144 | S a y f a
4.3.1. SqlDataAdapter Veritabanından çekilen veriyi DataTable’ımıza doldurmak veya DataTable’ımızda güncellenerek cachelenmiş verilerinizi veri kaynağınızda da güncellemek için kullanılır. - DataAdapter Disconnected Data ile çalışmak için tasarlanmıştır. - DataAdapter ve DataSet arasında direkt olarak bir bağlantı yoktur. DataAdapter ile DataSet’e veri doldurulurken database bağlantısı kapalı ise açılır, DataSet doldurulur ve işlem bittiği anda otomatik olarak kapatılır. Eğer bağlantı halihazırda açıksa herhangi bir hata vermeden işlemi yapar ve bağlantıyı kapatarak işlemini sonlandırır. Böylece bizlerin de fazla detayla uğraşmadan hızlıca işlemlerimizi yapmamızı sağlar. Constructor’da iki parametre ister. Birinci parametre Sql Sorgusu, ikinci parametre ise SqlConnection nesnesidir. Son olarak DataSet’e veriyi doldururken de Fill() methodu kullanılır. 4.3.2. DataTable Veri Kaynaklarından elde ettiğimiz bilgileri, veritabanından bağımsız olarak tablo formatında tutmamıza olanak sağlayan yapıdır. ADO.NET .Net Framework 2 ile birlikte veritabanından verileri alarak Dataset'e ihtiyaç duymadan direkt Datatable'e aktarabilme gibi bir yetenek kazandırılmıştır.
Disconnected Mimari kullanarak Northwind veritabanımızda bulunan ürünleri projemizde bulunan DataGridView kontrolüne aktaralım. Connected veya Disconnected mimari kullanırken SqlConnection nesnesi tanımlamalıyız. Sql Connection bizim sorgularımızın hangi server ve hangi veritabanı üzerinde hangi kullanıcı yetkisi ile çalışacağınız belirler. Örnek Uygulama //Formun Load Eventi private void Form1_Load(object sender, EventArgs e) { //Aşağıdaki kod satırında DataAdapter nesnesini oluşturuyoruz. Çalışacak sql sorgusunu belirtiyoruz. Yazdığımız sql sorgusunun hangi connection üzerinden çalışacağını belirliyoruz. SqlDataAdapter dap = new SqlDataAdapter("Select * from Products", new SqlConnection("Server=ALP1-BILGISAYAR\\EMPATI; Database=Northwind; UID=sa; PWD=123")); DataTable dt = new DataTable();//Yeni bir DataTable nesnesi oluşturuyoruz. dap.Fill(dt); //Veritabanından gelen ResultSet'i Oluşturulan DataTable nesnesine dolduruyoruz. dataGridView1.DataSource = dt;//DataTable'ı veri kaynağı olarak kullanıyoruz. }
145 | S a y f a
4.3.3. DataSet Veri kaynağından elde edilen verileri, veritabanı gibi bir modelde tutmak istediğimiz zaman bize yardımcı olan yapıdır. Veritabanımızda tablo yapıları bulunmaktadır. Tablo içerisinde ki veriler satır ve sütunlarda bulunur. Projelerimizde veritabanından veri çektiğimiz zaman, veritabanında bulduğu verileri tablo halinde elde edebiliriz. DataSet nesnesi içerisinde birden fazla DataTable bulundurarak bizim için bir çok tabloyu tek bir çatı altında toplar. Yani DataSet içerisinde veritabanından bağımsız olarak, veritabanımızdan gelen birden fazla tablo bulunabilir. Dataset aracılığı ile veri tabanımızdaki verileri tabloda bulunduğu yapısı ile uygulamamıza aktarabiliriz. İşin güzel tarafı bu verileri dataset'e bir kez aktardıktan sonra veriler sunucunun hafızasında saklanacağından artık database ile ilgimiz kalmamakta. Sunucunun hafızasında bulunan bu verilerle görüntüleme, silme, güncelleme gibi işlemlerimizi kolaylıkla yapabiliriz. Örnek Uygulama public Form1() { InitializeComponent(); } //Global Tanımlamalar DataSet ds = new DataSet(); //DataSet'e farklı eventlardan erişmek için Global tanımlama yapıyoruz. //Formun Load Eventi private void Form1_Load(object sender, EventArgs e) { SqlConnection baglan = new SqlConnection("Server=ALP1-BILGISAYAR\\EMPATI; Database=Northwind; UID=sa; PWD=123"); //DataAdapter kullanarak 3 farklı DataTable'a veritabanındaki tablolarımızı dolduruyoruz. SqlDataAdapter dap = new SqlDataAdapter("Select * from Categories", baglan); DataTable dt = new DataTable();//Yeni bir DataTable nesnesi oluşturuyoruz. dap.Fill(dt); SqlDataAdapter dap2 = new SqlDataAdapter("Select * from Products", baglan); DataTable dt2 = new DataTable(); dap2.Fill(dt2); SqlDataAdapter dap3 = new SqlDataAdapter("Select * from Orders", baglan); DataTable dt3 = new DataTable("Tablom"); //Constructor'da tabloya bir isim veriyorum. dap3.Fill(dt3); //Oluşturduğumuz DataSet nesnemizin içerisinde DataTable nesnelerimizi tablo olarak ekliyoruz. ds.Tables.Add(dt); ds.Tables.Add(dt2); ds.Tables.Add(dt3); } //Kategori listelemek için kullanılacak butonun click eventi
146 | S a y f a
private void btnKategorileriListele_Click(object sender, EventArgs e) { //DataSet içerisindeki tabloya ulaşmak için iki yöntem vardır. //--1.Yöntem : Sıra numarası ile dataGridView1.DataSource = ds.Tables[0]; //DataSet içerisinde bulunan DataTable'lar dan indexi 0 (dt Tablosu) olan } //Ürün listelemek için kullanılacak butonun click eventi private void btnUrunleriListele_Click(object sender, EventArgs e) { dataGridView1.DataSource = ds.Tables[1]; //DataSet içerisinde bulunan DataTable'lar dan indexi 0 (dt Tablosu) olan } //Sipariş listelemek için kullanılacak butonun click eventi private void btnSiparisleriListele_Click(object sender, EventArgs e) { dataGridView1.DataSource = ds.Tables["Tablom"]; //DataTable ismi ilede çağırabilirim. }
4.3.4. DataColumn & DataRow DataColumn; DataTable’da bulunan kolon nesneleridir. DataTable’a kod ile yeni bir kolon ekleyeceğimiz zaman kullanabiliriz. DataRow; DataTable’da bulunan her bir satırdır. DataTable’a yeni bir satır eklemek istediğimizde veya DataTable’da bulunan bir satırı almak istediğimizde DataRow nesnesini kullanılırız.
Aşağıdaki örnekde; YeniDoganBebekler isimli bir DataTable nesnesinde, doğan bebeklerin bilgileri tutulmaktadır. Kod ile yeni doğan bebeklerin bilgilerini ekleyip bu bebeklerden bir tanesini DataRow nesnesine aktarma işlemini gerçekleştireceğiz.
147 | S a y f a
Örnek Uygulama public partial class Form5 : Form { public Form5() { InitializeComponent(); } DataSet ds = new DataSet("Uyelik"); private void Form5_Load(object sender, EventArgs e) { //Tablo olusturulur... DataTable dt_Uyeler = new DataTable("Uyeler"); //Primary key kolonu olusturulur... DataColumn dc_UyeID = new DataColumn("UyeID"); dc_UyeID.DataType = typeof(int); dc_UyeID.AllowDBNull = false; dc_UyeID.AutoIncrement = true; dc_UyeID.AutoIncrementSeed = 1; dc_UyeID.AutoIncrementStep = 1; //Diger kolonlar olusturulur.. DataColumn dc_UyeAdi = new DataColumn("UyeAdi"); dc_UyeAdi.DataType = typeof(string); dc_UyeAdi.AllowDBNull = false; dc_UyeAdi.MaxLength = 24; dc_UyeAdi.Unique = true; DataColumn dc_Telefon = new DataColumn("UyeTelefonu");
148 | S a y f a
dc_Telefon.DataType = typeof(string); dc_Telefon.AllowDBNull = false; //Olusturulmus olan kolonlar tabloya eklenir.... dt_Uyeler.Columns.AddRange(new DataColumn[] { dc_UyeID, dc_UyeAdi, dc_Telefon }); //Tablonun primary key kolonu atanir... dt_Uyeler.PrimaryKey = new DataColumn[] { dt_Uyeler.Columns[0] }; //Tablo tamamen hazir olduguna gore db icerisine (dataSet) eklenir... ds.Tables.Add(dt_Uyeler); } private void btnUyeKaydet_Click(object sender, EventArgs e) { //Eklenecek satir olusturulur... DataRow dr_Eklenecek = ds.Tables[0].NewRow(); dr_Eklenecek[1] = txtUyeAdi.Text; dr_Eklenecek[2] = txtUyeTelefonu.Text; //Satiri olusturmak yetmez, o satiri ilgili tabloya eklemeniz gerekmektedir... ds.Tables[0].Rows.Add(dr_Eklenecek); //Son olarak dataSet uzerinde yapilan tum degisikler onaylanir... ds.AcceptChanges(); dgvUyeler.DataSource = ds.Tables[0]; txtUyeAdi.Clear(); txtUyeTelefonu.Clear(); } }
149 | S a y f a
ORM – Object Relational Mapping Entity Framework Microsoft tarafından geliştirilen ve yazılım geliştiricilerin katı sql sorguları yazmalarını ortadan kaldırarak bir ORM (Object Relational Mapping) imkanı sağlayan framework'tür. ORM ise ilişkisel veritabanı yönetim sistemlerine direkt olarak müdahale yerine nesneler aracılığı ile müdahale edilmesini sağlayan bir köprüdür diyebiliriz.
Entity framework'ün temel amacı uygulama geliştiricinin data işlemleri ile çok haşır neşir olmadan uygulama tarafına odaklanmasını sağlamaktır. Çok basit bir örnek olarak, klasik ADO.NET uygulamalarında bir bağlantının açılmasından ve kapatılmasından tamamen biz geliştiriciler sorumludur. Ancak entity framework kullandığınızda bu tür işlemlere siz karışmazsınız. Sorgunuzu hazırlar ve entity framework aracılığı ile bunu database'e iletirsiniz.
Piyasada bir çok ORM Framework'leri bulunmaktadır. Örnek olarak; DataObjects.Net, NHibernate, OpenAccess, SubSonic etc. Entity Framework vs..
5.1. ORM Nedir ?
ORM, Object Relational Mapping anlamına gelmektedir. İlişkisel veritabanı (RDBMS) ile nesneye yönelik programlamanın (OOP) arasında bir tür köprü özelliği gören ve ilişkisel veritabanındaki bilgilerimizi yönetmek için, nesne modellerimizi kullandığımız bir tekniktir”.
Basite indirgemek istersek: “Nesnelerimizi ilişkisel veritabanındaki tablomuza bağlayan ve veri alış-verişini bizim için yapan bir tekniktir”. ORM tekniği belli bir programlama diline bağlı değildir ve her OOP dilinde yazılabilir.
Avantajları:
Nesneye yönelik bir programlama metodu sunuyor Yazılan kodun veritabanı çeşidiyle bağımlılığı yok (Oracle, SQL Server, MySQL vs) SQL/JDBC bilmenize/yazmanıza gerek kalmadan çok kısa bir zamanda ve de çok daha az kod ile veritabanına bağlı bir uygulama yapabilirsiniz ORM araçlarının çoğu Open Source (Açık kaynak kodlu – yani bedava) ORM araçları, programcılara bir çok kolaylık sağlıyor ve içinde barındırdığı ek desteklerle bir çok sık görülen sorunlara çözüm sunuyor. (polymorphism, caching, transaksiyon, vs) Sektör içinde kullanılan Java ürünlerinin çoğunda popüler ORM araçları için ekler mevcuttur (Spring, Eclipse, vs) Otomatik kod üretmek ve ya SQL üretmek için bir çok ürün mevcuttur Çok daha iyi test edilebilir kod yazmamızı sağlar
150 | S a y f a
Dezavantajları:
Performans sorunları Bilgi alış-verişi sırasında kontrolün yüzde yüz sizin elinizde olmaması (Üretilen SQL bazen çok farklı olabilir) Kullanılan ORM aracını öğrenmek için harcanan zaman
5.2. Entity Framework
Entity Framework, bizim için database’i mizin yansımasını proje tarafına taşımamızı sağlayan veya projemizde ürettiğimiz database’i veritabanı tarafına taşımamızı sağlayan bir yapıdır.
Entity Framework’ün üç yapısı bulunmaktadır.
Database First Model First Code First
5.2.1. Database Yansımasını Almak
Veritabanının yansımasını almak, MsSQL’de bulunan veritabanımızdaki schema bilgisinin visual studio tarafına yansıtılmasıdır. Visual studio MsSQL’den gelen tabloları class olarak tanır, tablolarda bulunan kolonları ise property olarak okur.
Bir proje içerisinde veritabanının yansımasını almak için aşağıdaki adımları takip edebilirsiniz.
1.Projeye sağ tıklıyoruz. 2.Add > New Item diyerek yeni bir bileşen eklemek için pencereyi açıyoruz. 3.Sol tarafta bulunan Data sekmesine geçiyoruz. 4.Ado.Net Entity Data Model seçeneğini seçip Tamam butonuna tıklıyoruz.
151 | S a y f a
Edmx uzantılı dosyamızı oluşturuyoruz. .edmx (Entity Data Model.net) dosyamız bizim veritabanımızın yansmasının alındığı dosya olacaktır.
Add butonuna tıkladıktan sonra ‘Entity Data Model Wizard’ penceresi açılacaktır. Bu pencereden ‘Generate from Database’ seçeneğini seçip Next butonuna tıklıyoruz.
152 | S a y f a
Bu pencereyi geçtikten sonra aşağıda gördüğünüz veritabanı bağlantı penceresi ile karşılaşacağız.
1.Which data connection should your application use to connect to the database? Başlığı altında visual studio’nun veritabanına bağlanması için bir bağlantı belirtmemiz gerekmektedir. Eğer visual studio’da daha önce bir bağlantı tanımladıysak ComboBox’dan bu bağlantıyı seçebiliriz.
2.Eğer bağlantıyı ilk kez tanımlayacaksak ‘New Connection’ butonu ile yeni bir bağlantı tanımlama penceresi açabiliriz.
3.Bağlantımızı seçtikten sonra oluşacak ‘Connection String’ de şifreyi saklamak ile ilgili bilgi vermemizi istiyor. No seçeneğini işaretlersek Sql kullanıcı şifremiz Connection String’de yer almayacaktır. Yes seçeneği ise şifremizi connection string’e yazdıracaktır.
5.Oluşan ‘Connection String’ web config dosyasına hangi isim ile kaydedilecek. İsmi belirleyebiliriz.
153 | S a y f a
Next butonuna basarak devam ediyoruz.
Yukarıdaki ekranda hangi database nesnelerini yansımaya dahil edeceğini soruyor. Sadece istediğimiz tabloları, viewları ve stored procedure’leri yansımaya dahil edebiliriz.
Pluralize singularize generated object names -> Seçeneği tablo isimlerini class olarak yazdırırken isimleri tekilleştirmeyle ilgili bir ayardır. Bu seçenek yanlızca ingilizce veritabanlarında çalışır. Aşağıda bulunan Model Namespace bu yansımayı proje içerisinde kullanırken hangi ‘Name Space’ ile kullanacağımızı belirtmemize izin verir. Daha sonra ‘Finish’ butonuna basarak yansımayı çıkartabiliriz.
5.2.2. Database First Hazır bir database’i miz varsa, o database’den Visual Studio tarafına yansıma almamızı sağlar. Yani tabloları Class olarak, kolonları ise property olarak aktarır. Bizler o class’ı kullanarak veritabanı işlemlerimizi gerçekleştirebiliriz. Büyük database’ler içinde kullanılabilir. Ama tablo sayısı çok fazla artıyorsa sıkıtılar çıkartabiliyor.
154 | S a y f a
Anlatılacak Örnek- Listeleme İşlemi NorthwindEntities db = new NorthwindEntities(); dataGridView1.DataSource = db.Customers.ToList();
Entity Framework’de listeleme yaparken tabloyu belirtmek yeterlidir. Ama sadece tabloyu belirttiğimizde, bize bir hata çıkartır. Bunun sebebi tablodan sonra gelecek değerlerin bir liste olduğunu (Generic List) belirtmemiş olmamızdan kaynaklanmaktadır.
Tablodan sonra ToList() metodunu eklersek dönen verilerin listesi DataSource olarak kullanılabilir duruma gelir.
5.2.3. Code First Kod ile daha fazla işleme müdehale ederek, SQL tarafında olmayan bir veritabanını oluşturmak için kullanılır. Bir programı birden fazla sisteme kurmak için kolaylık sağlar. Program içerisinde veritabanının oluşmasını sağlar. Bunun dışında değişiklik yapıldığında veritabanında da bu değişiklikleri yapmayı sağlayabiliriz.
Ayrıca Entity Framework Code First yaklaşımında 15-22 tablo arası tablo oluşturmaya çalışıldığında sıkıntılar çıkartabiliyor. Entity Framework çok büyük projelerde kullanılamaz.
Code First yaklaşımını kullanarak bir veritabanı oluşturma işlemi yapalım. Bu işlem için öncelikle “Windows Forms Application” projesi içerisinde aşağıda ki classları oluşturalım.
Category.cs public class Category { public int CategoryID { get; set; } public string CategoryName { get; set; } public string Description { get; set; } }
Product.cs public class Product { public int ProductID { get; set; } public string ProductName { get; set; } public int UnitsInStock { get; set; }
155 | S a y f a
public decimal UnitPrice { get; set; } public int CategoryID { get; set; } }
Yukarıda oluturduğumuz classlar bizim veritabanında bulunan tablolarımızın classları olacaktır. Code First yaklaşımında oluşturduğumuz classları kullanarak veritabanı oluşturulur.
Database First yaklaşımında, Entities isimli bir class bulunuyordu.. Bu class bizim tablolarımızı içerisinde tutardı. Database First yaklaşımında Entities classı kendi oluşuyordu fakat Code First yaklaşımında bu classı kendimiz yazmalıyız. Bunun için aşağıdaki NorthwindShopEntities isimli classı oluşturalım.
Entity Framework mimarisinin güzelliği burada devreye girer. NorthwindShopEntities classını doğru bir biçimde şekillendirdiğimizde içerisine verdiğimiz classlar veritabanında düzgün bir şekilde oluşturulabilir.
Bu işlemi yapmak için projemize “Entity Framework.dll” yüklememiz gerekiyor.
NorthwindShopEntities.cs public class NorthwindShopEntities : DbContext //Miras Aldık { }
Yukarıda oluşturduğumuz class içerisinde istediğimiz yapıyı kullanabilmek için, classımızı diğer classlardan ayırmamız gerekmektedir. Bunun için “NorthwindShopEntities” classımıza “DbContext” classımızdan miras almamız gerekmektedir. “DbContext”, “System.Data.Entity” namespace altında bulunmaktadır. Daha sonra oluşturduğumuz “NorthwindShopEntities” classımız içerisinde property’leri belirtmemiz gerekiyor.
NorthwindShopEntities public class NorthwindShopEntities : DbContext //Miras Aldık { /* Syntax */
“NorthwindShopEntities.cs” classımızı yukarıdaki şekilde düzenliyoruz. Şimdi yukarıda bulunan classı tetikleterek veritabanımızı oluşturmamızı sağlayabiliriz. Formumuzun Load eventinde aşağıdaki kodları yazarak veritabanımızı oluşturabiliriz.
Form1.cs private void Form1_Load(object sender, EventArgs e) { NorthwindShopEntities db = new NorthwindShopEntities(); var result = db.Categories.ToList(); }
Yukarıdaki işlem aslında bir veri çekmek işlemidir ama Code First yaklaşımında amacımız ilk çalıştırmada kategorileri çekmek değil, tablolarımızın oluşturulmasını sağlamaktır. Projeyi çalıştırdığımızda kısa bir beklemeden sonra form açılacaktır. Şimdi Sql Server Management Studio’yu açıyoruz. NorthwindShop isimli bir veritabanı oluşup oluşmadığını kontrol ediyoruz. Veritabanının oluşmadığını görüyoruz. Bunun sebebi ne olabilir?
Tabikii de sebebi bu yapıyı veritabanına oluşturabilmesi için gerekli ConnectionString tanımlamasını yapmadık. Bu sebeple arka tarafta bu işlemi localdb olarak oluşturdu. Biz bir connection string tanımlayıp bu işlemi veritabanı üzerinde yaptırmamız gerekmektedir.
Bu işlem için ilk adım “App.config” içerisinde bir ConnectionString tanımlaması yapmalıyız. App.config içerisinde ConnectionStrings içerisinde aşağıdaki bağlantıyı tanımlıyoruz. ConnectionString içerisinde verdiğimiz veritabanı ismi ile Database oluşturulacaktır. Bizim database oluşturma işlemini Sql Management Studio tarafında yapmamıza gerek yoktur.
ConnectionString oluştururken dikkat etmemiz gereken çok önemli bir nokta daha var.
157 | S a y f a
ConnectionString gerekiyor.
tanımlamasını
ConfigSection’dan
önce
yapmamamız
App.config
Appconfig içerisinde aşağıda bulunan siyah renk ile yazılmış, altı çizili satırı silelim.
App.config
Yukarıda siyah ile işaretlenmiş satırları silebiliriz. Siyah ile işaretlenmiş tanımlama, Entity Framework tarafından oluşturulmuş bir ifadedir. Bu işlemden sonra bağlantımızıda oluşturduğumuza göre artık “NorthwindShopEntities.cs” classı içerisinde gerekli düzenlemeyi yaparak veritabanı oluşturma işleminin local’de değilde, veritabanında oluşmasını sağlayabiliriz.
NorthwindShopEntities.cs public class NorthwindShopEntities : DbContext //Miras Aldık { //Constructor Metot public NorthwindShopEntities() { } public DbSet Products { get; set; } public DbSet Categories { get; set; } }
DbContext’den miras almıştık. Şimdi bu mirası kullanarak veritabanımıza oluşturma işlemlerimizi gerçekleştiriyoruz. Bu işlem için base classımıza (DbContext) connection string göndermemiz gerekiyor. Bu işlem için aşağıdaki kodları uygulayalım.
NorthwindShopEntities.cs public class NorthwindShopEntities : DbContext //Miras Aldık { public NorthwindShopEntities():base("NorthwindShopDbCon") kullanacak {
//Buradaki
bağlantıyı
} public DbSet Products { get; set; } public DbSet Categories { get; set; } }
Yukarıda DbContext classının hangi ConnectionString’i kullanacağını belirtiyoruz. Verdiğimiz ConnectionString üzerinden veritabanına bağlantıları oluşturacaktır. Sql Server Management Studio’yu arayüzümüzü açıp veritabanımızı kontrol edelim.
159 | S a y f a
Yukarıdaki resimde gördüğünüz gibi ConnectionString’de belirttiğimiz veritabanı ismi ile veritanımız, “NorthwindShopEntities.cs” classımızda belirttiğimiz tablo isimleri ile veritabanı tablolarımız oluşturuldu. Veritabanımız içerisinde bulunan tabloların kolonları, classlarımız (Product, Category) içerisinde bulunan propertyler ile belirlendi. Ama yukarıdaki tabloların görünümünü Standart olarak kolon tiplerinin otomatik olarak belirlendiğini görürüz.
Örneğin kategori adı kolonumuz nvarchar(MAX) olarak belirlenmiştir. Aynı şekilde Products tablosunda ki UnitPrice kolonu decimal olarak belirlenmiştir. Ayrıca string tipte olan kolonlar boş geçilebilir olarak işaretlenmiştir. Bunun dışında Propertylerde ilk yazılan property Uniq kolon olarak seçilmiş. Bu bilgilerin ardından diagrama bir göz atalım.
Aşağıdaki resimde diagramı görebilirsiniz.
Yukarıdaki bilgilere el ile müdehale edebilmemiz gerekmektedir. Bunun için C sharp tarafında bu bilgilere el ile müdehale edebileceğimiz bir yer var. Model 160 | S a y f a
oluşturulurken, propertyler ile ilgili ayarları yapabilirim. Bu yer benim için nesnesi override ettiğim yerdir. “NorthwindShopEntities.cs” içerisinde model oluşturulurken override işlemi gerçekleştirerek istediğim özellikleri ayarlayabilirim.
Ezmek istediğim yer OnModelCreating yani modelin oluşturulduğu andır. Burada modelimi yakalar ve içerisinde istediğim değişikliği yapabilirim.
Aşağıdaki kodları düzenleyip çalıştırdıktan sonra, Sql Server Management Studio’da bulunan NorhwindShopDB veritabanını silelim. Daha sonra aşağıdaki kodu çalıştıralım.
NorthwindDbEntities.cs //Model oluşturulurken protected override void OnModelCreating(DbModelBuilder modelBuilder) //Değer ModelBuilder'da yakalanır { //Ürün adı boş geçilemez, uzunluğu 100 karakter olsun //Model Builder içerisinde Product değerimizi yakaladık. Property’leri içerisinden ProductName’in maxLenght bilgisini belirledik ve boş geçilemez olarak ayarladık. modelBuilder.Entity().Property(p => p.ProductName).HasMaxLength(100).IsRequired(); }
IsRequired => Boş Geçilemez. HasMaxLength => Maximum karakter sayısı
Yukarıdaki işlemden sonra veritabanımızı kontrol edelim. Kolonumuzun özellikleri max length değeri 100 ve boş geçilemez olarak düzenlenmiş olacaktır.
161 | S a y f a
Yukarıda görüldüğü üzere veritabanımızda bulunan Products tablosunun ProductName kolonunun DataType’ı 100 olarak düzenlenmiş ve boş geçilemez olmuştur.
Peki biz veritabanı oluşturma işlemi sırasında her seferinde veritabanını Sql Server Management Studio’dan silecekmiyiz? Tabi ki de hayır. Biz bu işlem için bir strateji belirleyerek çalışabiliriz. Oluşturacağımız strateji biz projemizi her çalıştırdığımızda Veritabanını silecek ve tekrardan oluşturacaktır.
NorthwindDbEntities.cs //Model oluşturulurken protected override void OnModelCreating(DbModelBuilder modelBuilder) //Değer ModelBuilder'da yakalanır { //Stratejimizi belirleyelim. (Model değiştiğinde, veritabanını sil ve modeli tekrar oluştur) Database.SetInitializer(new DropCreateDatabaseIfModelChanges()); //Ürün adı boş geçilemez, uzunluğu 100 karakter olsun //Model Builder içerisinde Product değerimizi yakaladık. Property’leri içerisinden ProductName’in maxLenght bilgisini belirledik ve boş geçilemez olarak ayarladık. modelBuilder.Entity().Property(p => p.ProductName).HasMaxLength(100).IsRequired(); }
5.2.3.1. Tablolar Arası Bağlantıyı Ayarlamak
Şu ana kadar modellerimizi, veritabanımızı, tablolarımızı ve kolonlarımızı oluşturduk ama yaptığımız işlemlerde bir eksik var. Bu eksik tablolar arası 162 | S a y f a
bağlantıların kurulmamış olmasıdır. Oluşturduğumuz modeller üzerinden tablolarımız arasında bağlantılarımızı kurabiliriz.
Product ve Category tablomuzda bire çok bir bağlantı söz konusudur. Bizim iki tablo için bire çok bağlantıyı uygulayabilmemiz gerekiyor. Bu işlem için modellerimiz içerisinde bu bağlantıyı tanımlamalıyız. Bu işleme ‘Mapping’ adı verilir.
5.2.3.1.1.
Mapping Uygulamak
Mapping işlemi tablolarımız arasında bağlantı kurmamızı sağlar. Classlarımızı aşağıda ki gibi düzenlediğimiz de Mapping işlemini tamamlamış oluruz. Burada dikkat etmemiz gereken nokta, veritabanındaki normalizasyon kurallarımızdır. Northwind veritabanı üzerinden hareket ettiğimizde aşağıdaki sonuca ulaşırız.
Bir ürünün, bir kategorisi vardır. Bir kategoriye ait birden fazla ürün vardır.
Yukarıdaki bilgilere göre bağlantımızı kurmamız gerekmektedir. Tablolar arası bağlantıyı hem ‘Product.cs’, hemde ‘Category.cs’ classı içerisinde tanımlamalıyız.
Product.cs public class Product { public int ProductID { get; set; } public string ProductName { get; set; } public int UnitsInStock { get; set; } public decimal UnitPrice { get; set; } public int CategoryID { get; set; } //Mapping public Category Category { get; set; } }
Category.cs public class Category { public int CategoryID { get; set; } public string CategoryName { get; set; } public string Description { get; set; }
163 | S a y f a
//Mapping public List Products { get; set; } }
Product.cs içerisine eklediğimiz Category tipindeki property bu classların bağlantısını sağlamak içindir. Bu property her ürünün bir kategorisi olduğu anlamına gelir. Aynı zamanda Category.cs içerisine eklediğimiz List tipindeki property ise bir kategoriye ait birden fazla ürün olacağı anlamına gelecektir.
Yukarıda ki resimde gördüğünüz gibi tablolarımız arasındaki bağlantı oluşmuştur. Peki Categories tablosunda bulunan CategoryID ile Products tablosunda bulunan CategoryID’yi bağlayacağını nasıl anladı?
164 | S a y f a
Tabiki de ‘Mapping’ olarak belirlediğim Category tipimi, Product propertyleri içerisindeki CategoryID ile eşleştirdi. Eğer biz CategoryID isminde bir property oluşturmasaydık bu kolonu tabloları oluşturma sırasında kendi oluşturacaktır.
Not : MigrationHistory : SQL’e aktarılırken tutulan bilgiler tablosudur. Entity Framework 5’e kadar el ile oluşturulurdu. Default olarak oluşturulacak bilgiler tanımlanırdı. Yeni versiyonlarda otomatik olarak oluşturuluyor. 5.2.3.2. Primary Key Belirlemek
Oluşturduğumu modeller üzerinde PrimaryKey kolonunu belirleyebiliriz. Primary Key kolonunu iki yöntem ile belirleyebiliyoruz. Birinci yöntem Primary Key kolonunu bir attribute ile işaretlemektir. İkinci yöntem ise property ismi içeriside ‘ID’ tanımlamasını kullanmaktır. Aşağıda iki yöntemide inceleyebiliriz.
1.Yöntem - KEY
1.Yöntem – Key [Key] public int CategoryID { get; set; } //PK Kolonu public string CategoryName { get; set; } public string Description { get; set; }
Yukarıda Primary Key olarak belirlemek istediğimiz kolonu [Key] ile işaretliyoruz. Bu işaretleme belirtilen property’nin PK kolonu olacağını belirler. PK olarak belirlenmiş kolon otomatik olarak 1’den başlar ve 1 artar şeklinde belirlenecektir.
2.Yöntem – ID Eki
2.Yöntem – ID Eki public int CategoryID { get; set; } //PK Kolonu
Oluşturduğumuz bir property sonuna ID eklediğimizde bu kolon PK kolonu olarak algılanacaktır. 5.2.3.3. ModelBuilder İşlemleri
Yukarıda oluşturduğumuz yapıyı geliştirmeye devam ediyoruz. Önceki kodlarımızda oluşturduğumuz veritabanında ki kolonları istediğimiz gibi düzenlemeliyiz. Örneğin UnitPrice kolonu ‘decimal’ oluşturulurken, aslında bu kolon ‘money’ tipinde oluşturulmalıydı.
165 | S a y f a
Sıradaki işlemimiz veritipini değiştirmek olacaktır. Bu işlem için ‘NorthwindShopEntities.cs’ dosyasını açalım. Dosyamızı açtıktan sonra aşağıda ki kod’u projemize ekleyelim.
HasColumnType ile kolon tipini belirleyebilirim. Burada dikkat edilmesi gereken nokta string olarak verilecek kolon tipi Sql’de bulunan kolon tipleri ile uyumlu olmak zorundadır. Varsayılan olarak verilen IsRequired ve IsOptional değerler, belirtilen kolon tipine göre ayarlanır. Müdehale edilmediğinde Reference Type ve Value Typelara göre değişiklik gösterir. Reference Type’lar null değer alabileceğinden veritabanı tarafından null geçilebilir olarak algılanmaktadır. Yukarıdaki kodu ekledikten sonra classımız aşağıdaki gibi görünecektir.
NorthwindShopEntities.cs public class NorthwindShopEntities : DbContext { public NorthwindShopEntities() : base("NorthwindShopDBCon") { } public DbSet Products { get; set; } public DbSet Categories { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { Database.SetInitializer(new DropCreateDatabaseIfModelChanges()); modelBuilder.Entity().Property(p => p.ProductName).HasMaxLength(100).IsRequired(); //Aşağıdaki satır ile veritipini money tipi yapıyoruz. modelBuilder.Entity().Property(p => p.UnitPrice).HasColumnType("money"); } }
UnitsInStock int tipinde, Required olarak aktarılacak bir property’dir. Bu sebeple UnitsInStock bilgisini burada belirtmemize gerek yoktur.
Categories tablosunda CategoryName boş geçilemez olması gerektiğinden bu kolonu yönetmemiz gerekir. Ayrıca CategoryName için maximum karakter
166 | S a y f a
sayısını belirlemeliyiz. Aşağıda bulunan iki satırı ‘NorthwindShopEntities.cs’ dosyamıza ekleyelim.
Yukarıda CategoryName kolonunu IsRequired komutu ile boş geçilemez olarak belirledik. HasMaxLength komutu ile CategoryName kolonunun sınırını 50 karakter olarak belirledik.
Description kolonunu IsOptional, yani boş geçilebilir olarak belirledik. IsOption komutunu kullanmasaydım varsayılan olarak bu kolon boş geçilebilir bırakılacaktır.
Yukarıdaki yeni kodları ‘NorthwindShopEntities.cs’ dosyası içerisine ekledikten sonra projeyi çalıştıralım ve veritabanımızı inceleyelim.
Görüldüğü üzere modeli ezmemize bağlı olarak istediğimiz özellikler belirlenmiştir. Dikkat etmemiz gereken bir nokta veritabanı üzerinde bir tablo veya diagram açıksa değişiklikleri uygulayamayabiliyor. Bu sebepten projeyi tekrar çalıştırırken veritabanına ait tüm pencerelerin kapalı olduğuna emin olmalıyız.
Sırada yine çok kullanışlı olacak bir özellik var. Class içerisinde, veritabanında oluşturulmasını istemediğim bir property eklemek istediğimizde ne yapacağız? Sadece kullanmak için oluşturacağımız bu property’i aşağıdaki gibi
Yukarıdaki satırı projenize eklediğinizde Description kolonu oluşmayacaktır. Bir property sadece kullanılmak için oluşturulduğunda veritabanına oluşturulmasına gerek yoktur.
Kolonları oluşturma işlemlerini inceledik, şimdide propertylerimiz ile veritabanında bulunan kolon isimlerini farklı kullanmak istediğimizde, nasıl isim belirleneceğini incelyelim. Aşağıdaki kod satırı bir property kolon olarak oluşturulurken ismini farklı vermek için kullanılmaktadır. modelBuilder.Entity().Property(p => p.ProductName).HasColumnName("UrunAdi");
Farklı isim kullanma işlemini tablolar içinde yapabiliriz. modelBuilder.Entity().ToTable("Urunler");
5.2.4. Entity Framework Performans Karşılaştırma Connected, Disconnected ve Entity Framework performans kıyaslaması yapacağız. Bu 100%’lük bir kıyaslama olmayacaktır. Çünkü bu işlemi ayrı ayrı projelerde yapmamız gerekecektir. Ama yinede bize bir fikir verecektir.
Connected Mimari DateTime baslangic = DateTime.Now; SqlConnection cnn = new SqlConnection("Server =.;Database=Northwind;UID=sa;PWD=123"); SqlCommand cmd = new SqlCommand("Select * From Orders", cnn); if (cnn.State == ConnectionState.Closed) cnn.Open(); SqlDataReader dr = cmd.ExecuteReader(); if (dr.HasRows) { while (dr.Read()) { lstConnected.Items.Add(dr["OrderID"]); } } cnn.Close(); DateTime bitis = DateTime.Now; TimeSpan fark = bitis - baslangic; lblConnected.Text = fark.Milliseconds.ToString();
Connected mimari her seferinde güncel veriyi adım adım veritabanından çekeceği için yavaş çalışacaktır.
168 | S a y f a
Disconnected Mimari DateTime baslangic = DateTime.Now; SqlDataAdapter dap = new SqlDataAdapter("Select Database=Northwind; UID=sa; PWD=123"); DataTable dt = new DataTable(); dap.Fill(dt); lstDisconnected.DataSource = dt; lstDisconnected.DisplayMember = "OrderID";
Entity Framework ilk seferinde, yani yansıma Cache’e gelene kadar yavaş çalışır. Daha sonraki çalışmalarda entity framework hızlanacaktır. Entity Framework’un instance’ı nı global’e taşıdığımızda proje derlenirken yansıma alınacağı için hızı artacaktır.
5.2.5. Entity Framework Veritabanı İşlemleri 5.2.5.1. Entity Framework Insert İşlemi Öncelikle veritabanımız içerisinde bir tane veritabanı oluşturuyoruz.
Veritabanı Adı : TelefonRehberiDB Tablo Adı : Kisiler
Kisiler Tablosunda Bulunan Kolonlar :
169 | S a y f a
KisiID int Adi nvarchar(50) Soyadi nvarchar(50) TelefonNumarasi nvarchar(50)
Daha sonra veritabanımızın yansımasını alıyoruz ve resimde görünen form görünümünü hazırlıyoruz.
5.2.5.2. SaveChanges SaveChanges() : Kaydetme işlemini yapar. Bu satır işlemin sonunda yazılmazsa veritabanına yazmayı gerçekleştirmez üst satırda db.TabloAdi.Add dediğimiz kısım tabloya eklemeyi yapar ama kayıt etmez. Kayıt yanlızca sanal bir tabloda yapılır Db.SaveChanges metodunu gördüğü zaman kayıt işlemini gerçekleştirir.
Bunun Sebebi her seferinde veritabanı bağlantısını açmamak içindir. Örneğin birden fazla ekleme işlemi yaparken, her biri için ayrı ayrı veritabanına bağlantı açacak ekleyecek kapatacak. Ama bu yöntem ile toplu ekleme, güncelleme ve silme işlemlerinde tek bir kez veritabanı bağlantısı kurarak tüm işlemleri gerçekleştirmiş olurum.
170 | S a y f a
Not : Metot’u if yapısında şart yazdığımız alana yazıp, CTRL + . diyerek Generate Metot olarak oluşturursak metodun geriye dönüş tipi bool olacaktır. 5.2.5.3. Entity Framework ID’ye Göre Veri Getirme İşlemi Güncelleme işlemi yapmamız için kayıtlı olan verinin ilgili kontrolden ID değerini elde etmemiz gerekiyor. Bu ID’ye göre Class’ımızın tipinde nesnemizi elde edeceğiz. Elde ettiğimiz nesne üzerindeki bilgileri değiştirip güncelleme işlemini yapacağız. Burada dikkat edilmesi gereken nokta; güncellenecek olan nesneyi global’de tanımlamaktır. Birden fazla Event içerisinden erişebilmemiz için (Güncelleneceği DataGridView içerisinde yakalıyoruz, Güncelleme işlemini Button’da yapıyoruz gibi..) globalde tanımlamak gerekmektedir. Yukarıdaki işlemi DataGridView nesnesi için uygulayacağız. Örnek kodlar aşağıdadır.
ID ye Göre Nesne Getirme Kisiler guncellenecek; //Güncellenecek nesnemizi global’de tanımlıyoruz. private void dgvKisiler_DoubleClick(object sender, EventArgs e) { //DataGridView kontrolünün MultiSelect özelliği kapatılmalı ve FullRowSelect özelliği açılmalıdır. if (dgvKisiler.SelectedRows.Count > 0) //Eğer DataGridView kontrolünde seçim yapılmamışsa { int id = Convert.ToInt32(dgvKisiler.SelectedRows[0].Cells[0].Value); //DataGridView'da bulunan ID hücresindeki değeri yakala guncellenecek = db.Kisiler.Find(id); //Bu ID'ye göre nesnemizi getiriyoruz. txtTelNo.Text = guncellenecek.TelefonNumarasi; txtSoyad.Text = guncellenecek.Soyadi; txtAd.Text = guncellenecek.Adi; } }
Yukarıda yaptığımız işlem veriyi güncelleyecektir. Ama daha doğru bir yöntemi bulunmaktadır. Bu yöntem DataGridView’da kullanılmıyor. Bunu DataGridView’da kullanamamızın nedeni, ben Güncelle Butonuna çift tıkladığımda DataGridView’da bulunan eski halini bir bütün olarak elde edemiyorum.
db.Kisiler.Find ile ID ile veritabanındaki bilgiyi güncellenecek olarak tutmuş oluyoruz. db.Entry(guncellenecek).CurrentValues.SetValues(yeniHali); veritabanında bulunan güncellenecek ile yeni halinin güncellemesini söylüyoruz.
satırında ise değişen değerlerini
Bunun bize ne gibi bir yararı var? Birinci Yöntemde; biz 20 kolonluk bir tabloda güncelleme yaptığımızda ilk yöntem tüm kolon bilgilerini veritabanına gönderecektir. İkinci Yöntemde ise; sadece değişiklik yaptığımız kolonlar veritabanında güncellenecektir. Böylece güncelleme işleminde performans kaybı azalacaktır. 5.2.5.4. Entity Framework Silme İşlemi
Silme İşlemi int id = Convert.ToInt32(item.Cells[0].Value); Kisiler silinecek = db.Kisiler.Find(id); db.Kisiler.Remove(silinecek); db.SaveChanges();
Silme İşlemi – Kısa Yöntem int id = Convert.ToInt32(item.Cells[0].Value); db.Kisiler.Remove(db.Kisiler.Find(id)); db.SaveChanges();
Toplu Silme İşlemi private void btnSil_Click(object sender, EventArgs e) { if (dgvKisiler.SelectedRows.Count > 0) { foreach (DataGridViewRow item in dgvKisiler.SelectedRows) { int id = Convert.ToInt32(item.Cells[0].Value); db.Kisiler.Remove(db.Kisiler.Find(id)); } db.SaveChanges();
172 | S a y f a
VerileriCek(); } }
5.2.5.5. Entity Framework WHERE Kriteri (Extension Metot) Extension Metotları kullanmak için, lambda expression dediğimiz bir yapıyı kullanırız. SQL’de kullandığımız tabloya, tabloyu temsil edecek bir isim vermek gibi burdada temsili bir isim veriyoruz.
Where Kriteri Kullanma dgvKisiler.DataSource = db.Kisiler.Where(k => k.Adi.StartsWith(txtArama.Text) k.Soyadi.StartsWith(txtArama.Text)).ToList();//lambda expression
||
Yukarıdaki kod’da Kisiler.Where’den sonra Kisiler’i bundan sonra k harfi ile çağıracağımı belirtiyorum. => : Öyleki anlamına gelir.
k öyleki dedikten sonra bool bir değer vermeliyim. Bu şartı sağlayan değerler DataSource olarak verilecektir.
Anlatılacak Örnek – Extension Metotlu Yöntem //Fiyati 20 ile 50 arasinda olan urunlerin UrunId,UrunAdi,Fiyati,StoktakiMiktari ve KategoriAdini getiren sorguyu yazalım. dgvSonuclar.DataSource = db.Products.Where(p => p.UnitPrice > 20 && p.UnitPrice < 50).Select(p => new { UrunId = p.ProductID, UrunAdi = p.ProductName, Fiyati = p.UnitPrice, StoktakiMiktari = p.UnitsInStock, KategoriAdi = p.Category.CategoryName }).ToList();
Yukarıdaki sorguda KategoriAdı istendiği için sorgu içerisinde Inner Join olacaktır. Ama Entity Framework bizi join işlemlerinden kurtarıyor. Lambda Expression ile Where kriteri verebiliyoruz. Extension Metot yönteminde sorguyu istediğim kadar uzatabilirim. ‘.’ Ile istediğim kadar extension metot ekleyebiliyoruz. UrunID, UrunAdi, Fiyati, StoktakiMiktari ve KategoriAdi yazdığımız yerler bizim kolonlara verdiğimiz isimleri temsil eder.
Entity Framework sorgusu yazmanın iki yöntemi var. 1.Extension Metotlu Yöntem 2.Linq Sorgusu olarak yazmak (Language Integrated Query)
173 | S a y f a
5.2.5.6. Extension Metot Nedir? Extension methods sadece static classlar içinde tanımlanabilen, parametre tanımlamalarında türden önce this ifadesini kullandığımız static metodlardır.
Örnek Bir Extension Metot public static int ToInt32Ext(this string s) //this keyword’ü ile extension metot tanımlıyoruz. { return Int32.Parse(s); }
Kullanımı string
s int
= i
label1.Text = i.ToString();
=
s.ToInt32Ext();
//Extension
"9";
method
kullanımı
Kullanırken metot parantezleri arasında parametre göndermek yerine, tipimizin sonuna .ToString metodunu ekler gibi, oluşturduğumuz metodu ekledik. 5.2.5.6.1.
Lambda Expression
Lambda İfadeleri, değişkenlere değer atamak için kullanılan sadeleştirilmiş anonim (isimsiz) fonksiyonlardır. Bu fonksiyonlar matematikteki ve bilgisayar bilimlerindeki Lambda Calculus'un C# ve Visual Basic uygulamasıdır. Lambda İfadeleri kullanarak parametre geçilebilen ve değer döndüren isimsiz yerel fonksiyonlar oluşturabilirsiniz. Bu ifadeler genelde basit işlemleri bildirmekte kullanılabilir ve LINQ sorgularının yazımında çok işe yararlar.
Lambda Expression Oluşturmak i => i * 2 Örnekte olduğu gibi eğer (=>) opearatöründen önce yazılan i ifadesi bizim için seçtiğimiz nesneyi ifade edecektir. Operatörün sağında bulunan işlem i’nin temsil ettiği değeri 2 ile çarpacak ve sonucu döndürecektir. 5.2.5.6.2.
Linq
Sql’ de ki sorgulama dilini Csharp’a döktükleri halidir. Linq sadece Sql sorguları için değildir. Daha çok topluluk için yapılmış sorgulardır. Linq üç alt başlıktan oluşur. Linq to Object Linq to SQL Linq to Entity Örnek 1 : Fiyati 20 ile 50 arasinda olan ürünlerin UrunId, UrunAdi, Fiyati, StoktakiMiktari ve KategoriAdini getiren sorguyu yazalım.
174 | S a y f a
Örnek 1 : Linq var result = from p in db.Products where p.UnitPrice > 20 && p.UnitPrice < 50 //&& //p.Category.CategoryName == "Seafood" select new { UrunID = p.ProductID, UrunAdi = p.ProductName, Fiyati = p.UnitPrice, StoktakiMiktari = p.UnitsInStock, KategoriAdi = p.Category.CategoryName }; dgvSonuclar.DataSource = result.ToList();
Örnek 2 : Siparisler tablosundan MusteriSirketiAdi ,CalisanAdiSoyadi,SiparisIdsi,SiparisTarihi ve KargoSirketiAdini getiren sorgu
Daha az kod yazarak projelerimizi kısa sürede geliştirmemize olanak sağlar Performans sağlar ORM kullanarak proje geliştirmemizi sağlar Sql bilgisi olmadan proje geliştirilebilir
Dezavantajlar
Database işlemleri sırasında kontrol 100% olarak yazılımcı tarafından müdehale edilemez
176 | S a y f a
Ntier Architecture – Çok Katmanlı Yazılım Mimarisi Şu an’a kadar tek bir proje üzerinden, kodları bir bütün olarak çalıştırdık. Artık kodlarımızı yaptıkları işlere göre parçalamamızın zamanı geldi. Çok katmanlı mimari kodların yaptıkları işlere göre katmanlara ayrılarak çalıştırılması prensibine dayanır. Amaç, projeyi geliştirilebilir kılmak ve kolay yönetmektir.
Örneğin; bir web sitesi yaptınız. Web sitesi kısa sürede çok fazla kullanıcı tarafından benimsendi. Ama artık kullanıcıları browser bağımlılığından kurtarmak istiyorsunuz. Masaüstü uygulamaları ve mobil cihazlar için yeni projeler hazırlamanız gerekmekte. Ancak bu farklı platformlarda çalışacak uygulamalar için kodlarınızı tekrar tekrar yazmanız gerekmekte.. Web sitesinde yaptığınız SQL bağlantıları, veri kontrolleri ve classları tekrar tekrar yazmanız gerekmektedir.
Çok katmanlı yazılım mimarisi tam bu noktada devreye girer. Eğer sisteminizi çok katmanlı bir mimari olarak hazırlarsanız çok kısa sürede farklı platformlarda (web, desktop, mobil) uyumluluğu sağlayabilirsiniz.
Çok katmanlı yazılım mimarisi, kodların yaptıkları işlere göre ayrılması prensibine dayanır. Kodlar oluşturulan Class Library projelerinin içerisinde gruplanarak tutulur.
Katman sayısı arttıkça proje karmaşık hale gelebilir. Biz örneklerimizde dört katmanlı mimari örneğini inceleyeceğiz.
Katmanlar ile Çalışmanın Avantajları
Geliştirilebilirlik : Projedeki kodlar parçalanacağı için daha kısa sürede farklı platformlar için kod yazabiliriz. Kontrol Edilebilirlik : Kodlarımız parçalandığı için hata vermesi durumunda, daha az kod arasında hata aramamıza olanak sağlar. Temiz Kod Yazmak : Kodlar yaptıkları işlere göre ayrılacağından daha kolay kod okuyabilir ve kodlarımızı daha kolay kontrol edebiliriz. Performans: Her katman kendi üzerine düşen görevi yapacağı için, görev dağılımından ve gerekli zamanda kullanımdan dolayı performans seviyesi artacaktır.
Katmanlar ile Çalışmanın Dezavantajları
Zaman : Katmanlar ile çalıştığımızda normal bir projeye oranla biraz daha fazla zaman harcamış oluruz. Fakat bu durum projeyi farklı platformlar için hazırlamamız durumunda avantaja dönecektir. Katman sayısı arttıkça, katmanlar arası bağlantıları kurmakta zorlanabiliriz ve katmanlarımız kafa karıştırıcı bir hal alabilir.
177 | S a y f a
6.1. KATMANLAR
Çok katmanlı mimaride inceleyeceğimiz katman sayısı dörtdür. Katman sayısı yazılımcının isteğine göre artabilir.
6.1.1. Presentation Layer (WinUI (Windows User Interface), WEB)
Uygulamalarda ki, görünüm katmanıdır. Uygulamamızda kullanıcı ile iletişime geçebilen katmanlardır. Kullanıcıdan bilgi almak, kullanıcıya bilgi göstermek için kullanılırlar.
6.1.2. Entity Modellerimizi içerisinde barındıran katmandır. Projemiz içerisinde kullanılan modellerimiz Entity katmanı içerisinde tanımlanır. Entity katmanı tüm katmanlar tarafından tanınmak zorundadır. Bunun sebebi tüm katmanların Entity katmanında bulunan modelleri kullanabilmesi için, instance alma işlemi gerçekleştirmesidir.
6.1.3. Business Logic Layer (BLL)
Uygulamamızdaki verilerin kontrol ve güvenliğinden sorumlu olan katmandır. Kullanıcıdan aldığımız verileri kontrol eder ve güvenlik kontrollerinden geçirir. Eğer kullanıcıdan gelen veriler güvenli ve doğru formatta ise verileri Data Access Layer katmanına gönderir. Business Logic Layer katmanının bir diğer görevi ise, Presentation Layer ile Data Access Layer katmanı arasında bir köprü görevi görmesidir.
6.1.4. Data Access Layer (DAL)
Veriye erişim katmanıdır. Facade katmanı olarakta geçer. Data Access Layer katmanının görevi veritabanı işlemlerini yönetmektir. Veritabanı bağlantısını kurar, veri gönderir veya veri çekerek bu işlemlerin bilgilerini ve sonuçlarını BLL yardımıyla Presentation katmanlarına gönderir.
6.2. Katmanlı Mimarinin Çalışma Mantığı
Katmanlı mimarinin görevi kodlara tekrar kullanabilirlik sağlamak, kolay yönetmek ve geliştirilebilirlik sağlamaktır. Bu görevi yerine getirebilmek için kodlarımızı yaptıkları işlere göre katmanlara ayırırız. Kullanıcı ile iletişime geçecek olan katman (Presentation Layer) sadece kullanıcıdan bilgi almak ve bu bilgileri ilgili katmanlara göndermektir. Aynı zamanda kullanıcılara gösterilecek bilgileri listelemek ve mesajlar göstermekte Presentation katmanının görevidir.
BLL katmanının görevi ise, Presentation Layer tarafından alınan ve BLL katmanına gönderilen verileri kontrol etmek ve düzenlemektir. Gelen veriler doğru formatta ve güvenliyse, bu verileri DAL katmanına gönderir. Eğer gelen veriler veritabanı işlemine girmeye uygun değilse, verileri DAL katmanına göndermeden metotdan çıkacaktır.
DAL katmanının görevi, BLL’de kontrol edilmiş olan güvenli ve doğru formatta olan verileri veritabanı işlemine tabi tutmaktır. Gelen veriler BLL katmanında kontrol
178 | S a y f a
edildiğinden, güvenli oldukları için DAL katmanında kontrol edilmeden işleme alınır. Şimdi dört katmanlı mimariyi örnek ile inceleyelim.
Katmanlı mimari uygulaması için aşağıdaki projeleri tiplerini kullanacağız.
Windows Forms Application Class Library
Örneğimizde katmanlı mimari kullanarak Northwind veritabanından çalışan bilgilerini listeleyeceğiz. Amacımız kodlarımızı parçalara ayırarak “Windows Forms Application” projesinde çalışanları listeleyeceğiz.
Öncelikle bir solution oluşturuyoruz. Solution oluşturmak için Visual Studio programımızı çalıştırıyoruz ve aşağıdaki adımları takip ediyoruz.
Projemizin adını “NorthwindEmployees” olarak belirliyoruz. Solution oluştu şimdi içerisine katmanlarımızı eklemeye başlayacağız. Öncelikle “Entity katmanımızı ekliyoruz.“
Bir katman eklemek için Solution’a sağ tıklıyoruz > Add > New Project ile yeni bir proje oluşturma penceresini açıyoruz.
179 | S a y f a
Class library oluşturuyoruz, oluşturduğumuz class library projesinin adını “NorthwindEmployees.Entity” olarak yazıyoruz. Entity katmanı içerisinde “Employee.cs” classını oluşturuyoruz ve içerisinde bir Employee ile ilgili propertyleri çıkartıyoruz.
Employee.cs public class EEmployee { public int EmployeeID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Title { get; set; } public string City { get; set; } }
Entity katmanımıza gerekli classı ekledikten sonra, yeni class library projeleri oluşturuyoruz. Aşağıda ki listede gerekli olan Class Library’leri oluşturalım.
Yukarıda ki class libraryleri oluşturduktan sonra BLL katmanı içerisindeki “Class1.cs” dosyasını siliyoruz ve daha sonra yeni bir class ekliyoruz. Classımızın adı “BEmployee.cs” olacak şekilde ayarlıyoruz.
Hemen ardından DAL katmanınıda oluşturuyoruz. Daha sonra DAL katmanı içerisindeki “Class1.cs” dosyasını siliyoruz ve daha sonra yeni bir class ekliyoruz. Classımızın adı “DEmployee.cs” olacak şekilde ayarlıyoruz.
Şuanda üç katmanımızı oluşturduk. Son olarak Presentation Layer ‘ ımız olan WinUI katmanımızı oluşturmamız gerekiyor. Solution’a sağ tıklıyoruz ardından Add > New Project seçeneğine tıklıyoruz açılan pencereden “Windows Form Application” projesini seçip ismini ”NorthwindEmployees.WinUI” olacak şekilde yazdıktan sonra WinUI katmanımızı oluşturmuş oluyoruz.
Katmanlar arası bağlantıları belirlememiz gerekiyor.
6.2.1. Referans Alma İşlemi Projemizin içerisinde bulunan References’ a sağ tıklıyoruz açılan penceredeki Reference ‘ a tıklıyoruz.
Add
Karşımıza gelen Reference Manager (Referans Yönetimi) penceresidir. Referanslarımıza ekleme işlemi yapmak için seçtiğimiz referanslardan sonra OK butonuna tıklayarak reference ekleyebiliriz.
181 | S a y f a
Referans ekleme işleminide inceledikten sonra aşağıdaki referans verme işlemlerini yapabiliriz.
WinUI katmanımızın Referanslarını aşağıdaki listeye göre düzenliyoruz:
182 | S a y f a
WinUI katmanımız Entity katmanımızdan referans alır. WinUI katmanımız BLL katmanımızdan referans alır.
Tüm katmanlarımız Entitiy katmanımızdan aldığımız referans sayesinde katmanımızın içerisinde tanımlamış olduğumuz modellere ve modellerimizin içerisindeki property’lere erişebilmemize olanak sağlamış oluyoruz. WinUI katmanı içerisinde, BLL katmanımızdan aldığımız referans sayesinde BLL katmanında tanımlamış olduğumuz metotlara erişim sağlayabiliriz aynı zamanda BLL katmanımız WinUI katmanı ile DAL katmanımız arasında köprü görevi görüyor.
WinUI katmanımız içerisinde, DAL katmanı ile doğrudan bir bağlantı yoktur. İletişim BLL katmanı üzerinden sağlanır.
WinUI katmanımızın referanslarını yukarıdaki gibi oluşturduktan sonra BLL katmanımızın referanslarını oluşturmaya başlayabiliriz. BLL katmanımızın referanslarını aşağıdaki listeye göre düzenliyoruz:
BLL katmanımız Entity katmanından referans alır. BLL katmanımız DAL katmanından referans alır.
BLL katmanımız ile WinUI katmanımızdan gelen verilerin kontrollerini yaparız. Eğer veriler istenilen koşula uygunluk sağlıyor ise DAL katmanımıza gönderilip, veritabanında istenilen işlemi gerçekleştiririz. Eğer BLL katmanında gelen veriler istenilen şartları sağlamıyorsa DAL katmanına gönderilmez.
BLL katmanımızın referanslarını yukarıdaki gibi oluşturduktan sonra Entity katmanımızı oluşturmaya başlayabiliriz. Entity katmanımızın referanslarını aşağıdaki listeye göre düzenliyoruz.
Entity katmanımız WinUI, BLL ve DAL katmanlarımıza referans verir. Entity katmanımız hiçbir katmanımızdan referans almaz.
Entity katmanı modelleri tek çatı altında tutar. Entity katmanımızın referanslarını yukarıdaki gibi oluşturduktan sonra DAL katmanımızı oluşturmaya başlayabiliriz. DAL katmanımızın referanslarını aşağıdaki listeye göre düzenliyoruz:
DAL katmanı, Entity katmanından referans alır.
183 | S a y f a
DAL katmanına gelen veriler BLL katmanında kontrol edildikten sonra DAL katmanına geldiğinden veriler zaten kontrol edilmiş olduğundan dolayı DAL katmanı içerisinde veriler kontrol edilmez. DAL katmanının görevi veritabanı işlemlerini yapmaktır.
Referansların son durumunu aşağıdaki resimden kontrol edebilirsiniz.
Referansları doğru olarak ayarladıysanız, yukarıda ki gibi olması gerekmektedir.
Sırada classlarımız içerisinde bulunan metotların içeriğini doldurmak var. Metotları yaptıkları işlere göre dolduracağız.
İlk olarak DAL katmanımızda bulunan “DEmployee.cs” CalisanlariListele() metodumuzun gövdesini dolduruyoruz.
classı
içerisinde
ki
DEmployee.cs > public List CalisanlariListele() Metodu public List CalisanlariListele() { SqlConnection baglan = new SqlConnection("Server=.; Database=Northwind; UID=sa; PWD=123"); List calisanListesi = new List(); try { SqlCommand cmd = new SqlCommand("Select EmployeeID, FirstName, LastName, Title, City from Employees", baglan); if (baglan.State == ConnectionState.Closed) baglan.Open(); SqlDataReader dr = cmd.ExecuteReader(); if (dr.HasRows) { while (dr.Read()) {
Not : Yukarıdaki connection string’i kendinize göre düzenleyiniz.
DAL katmanında bulunan metodumuzun gövdesini doldurduktan sonra BLL katmanımızda WinUI’dan gelen isteği, DAL katmanına iletiyoruz.
Bemployee.cs > public List CalisanlariListele() Metodu public List CalisanlariListele() { DEmployee de = new DEmployee(); //DAL katmanındaki CalisanlariListele metodunu kullanmak için instance alıyoruz. return de.CalisanlariListele(); //DAL katmanından gelen sonucu döndürüyoruz. }
Son olarakda WinUI’da kullanıcı butona tıkladığında gelen isteği BLL’e iletiyoruz. BLL isteği DAL katmanına iletecek, DAL katmanı veritabanında gerekli sorguyu çalıştıracak ve sonucu Generic List olarak hazırlayacak. Hazırlanan Generic List (calisanListesi) return komutu ile BLL katmanına cevap olarak döndürülecek. BLL katmanına gelen cevap, BLL tarafından WinUI katmanına gönderilecek.
WinUI katmanı > private void btnCalisanlariListele_Click(object sender, EventArgs e) { BEmployee be = new BEmployee(); dataGridView1.DataSource = be.CalisanlariListele(); }
Yukarıda yaptığımız örnekde, kullanıcı butona tıkladığında çalışanları listeleme isteği
185 | S a y f a
yapmış olacak. WinUI gelen isteği BLL katmanına iletecek, BLL katmanı varsa gerekli kontrolleri yapacak ve isteği DAL katmanına iletecektir. DAL katmanı BLL’den geçen isteğin güvenli olduğunu bildiği için hiç bir kontrol yapmadan isteği gerçekleştirecek ve sonucu BLL katmanına gönderecektir. BLL katmanı DAL katmanından gelen isteği WinUI katmanına gönderecektir. WinUI katmanının görevi gelen sonucu kullanıcıya göstermek olacaktır.
Projeyi çalıştırmak istediğimizde proje çalışmayacaktır. Bunun sebebi Class Library’nin Executible olmamasından kaynaklanmaktadır. Hatayı düzeltmek için, WinUI katmanına sağ tıklayıp “Set as Startup Project” seçeneğini seçmeliyiz. Daha sonra projemizi derleyip çalıştıralım.
Gördüğünüz gibi çalışanlarımızın hepsi listelendi..
WCF - Windows Communication Foundation Windows Communication Foundation (WCF) Nedir? .Net Framework 3.0 ile hayatımıza giren WCF, istemciler ve servisler arasındaki mesajları göndermek için oluşturulan sistemleri geliştirmek için kullanılan API topluluğudur. Bu mesajlar, TCP, HTTP, MSMQ, Web Servisleri vb. gibi ortak taşıma protokolleri kullanarak Intranet ve Internet üzerinden gönderilebilir.
Windows Communication Foundation servis-yönelimli mimariyi temel alarak dağıtık uygulamalar geliştirmek için kullanılan, dağıtık mimari modelleri ve teknolojileri tek çatı altında birleştiren ve içerisinde bir çok hazır bileşen barındıran bir Framework API‘sidir.
Windows Communication Foundation Temelleri
186 | S a y f a
Mesajlar güvenli bir şekilde gönderilmekte ve dijital bütünlüğü için imzalanabilmektedir. WCF mesajlaşma işlemi için, istek/yanıt şeklinde basit mesaj desenlerinin yanı sıra iki kanal üzerinden iletişim gibi daha karmaşık desenleri desteklemektedir.
Diğer önemli özelliği ise Web Servisleri ile farklı platformlarda çalışabilmesidir yani WCF bu standartları uygulayarak Microsoft olmayan diğer platformlarda oluşturulmuş istemciler ya da servisler ile iletişim kurabilir. Service Oriented mimarisinin amacı, farklı platform ve diller ile iletişime geçebilen bir yapı oluşturmaktır.
Örneğin C Sharp programlama dili ile hazırlanmış bir seri işlemi, Java ile hazırlanan farklı bir projede kullanmak istiyoruz. Proje içerisinde yazdığımız kodları servis olarak hazırlayıp farklı platformlara veri gönderebilecek bir hale getirebiliriz.
Service Oriented Architecture Nedir? SOA, iş süreçlerine katılan değişik yazılım uygulamarının birbiriyle haberleşmek üzere yazılmamış olmalarına rağmen veri alışverişinde bulunmalarını sağlar.
Servis odaklı mimari, bilgisayarda sistemlerin işlevselliklerini, iş süreçleri etrafında gruplaştırarak sistem geliştirmesi ve bütünleştirilmesinde yol gösteren bir yazılım tasarımı felsefesidir.
SOA altyapısı, iş süreçlerine katılan değişik yazılım uygulamalarının birbirleriyle haberleşmek üzere yazılmamış olmalarına rağmen veri alışverişinde bulunmalarını sağlar.
SOA, geliştiricilerin başka kullanıcılar tarafından kullanılması amacıyla bir iletişim ağı üzerinden sundukları işlevleri ayrı birimlere ya da hizmetlere böler.
SOA, uygulamaya ait iş katmanlarının, farklı servisler üzerinden kullanılmasına olanak sağlar. Bu durumda hangi platformu kullanırsanız Kullanım hazırlamış olduğunuz web servisler aracılığıyla iş katmanlarını uygulamanızda kullanabilirsiniz. Unutulmaması gereken bir konu da SOA bir teknoloji değil farklı platformların ve programlama dillerinin birbiriyle haberleşmesini sağlayan bir mimari düşüncedir.
7.1. Service Oriented Architecture 7.1.1. SOA’nın Hedefleri ·
Servislere tekrar kullanılabilirlik kazandırmak,
·
Uygulamalar arasında bir standart belirlenerek birlikte çalışmayı arttırmak,
187 | S a y f a
· 7.1.2.
İş süreçlerinin ve ihtiyaçlarının daha kısa sürede karşılanmasını sağlamak,
SOA’nın Standartları
· Hizmetlerin mevcutta belirlenmiş olan standarlara uygun şekilde tanımlanmış olması, · Hazırlanan hizmetlerin farklı uygulamalar için kolay ve pratik bir şekilde entegre olması, ·
Bir servisin başka bir servise bağlı kalmadan çalışıyor olması,
·
Bir servisin birden fazla yerde kullanılabilicek şekilde tasarlanması,
· Hizmetlerin tanımlanırken en başta bir iş sürecine dahil olucak şekilde tanımlanması, · Hizmetin üzerinde bir değişiklik yapılırken bu hizmete bağlı olan uygulamaların bu süre zarfında etkilenmeyecekleri bir yapı oluşturulması, ·
Hizmet servisinin iyi bir şekilde ayarlanarak iyi bir performans sağlanması,
7.2. WCF Temelleri WCF’den Önce .Net Framework 3.0 ile birlikte hayatımıza giren WCF, daha önce kullanılan modelleri tek çatı altında kullanmayı hedeflemektedir. WCF den önce farklı yöntemleri kullanarak platformları ve farklı diller ile yazılan programları birbirleriyle haberleştirebiliyorduk.
.Net Remoting aynı ağ üzerinde olan (intranet) bilgisayarlar arası bağlantı kurmak için kullanılır. .Net Remoting kullanarak intranet bir bağlantı oluşturup aynı ağ içerisinde bulunan bilgisayarlara veri gönderebiliyorduk. .Net Remoting üzerinden şirket çalışanlarını intranet bir bağlantı ile şirket için yayınlayabiliriz.
HTTP Web Service ise XML teknolojisini kullanarak internet üzerinden bütün bilgisayarlara yayın yapabilir. WCF’den önce .Net Remoting bir bağlantı ile bir uygulama geliştirdiğimizde, aynı işi XML Web Service ile internetten yayına açmak istediğimizde, birde XML Web Service uygulaması yazmamız gerekiyordu. Yukarıda ki örneğimizden devam edelim. .Net Remoting ile birlikte bir de XML Web Service projesi oluştururuz.
Yukarıda bahsettiğimiz teknolojileri daha detaylı olarak inceleyeceğiz. Şimdi örneğimiz üzerinden WCF’i tanımlayalım.
188 | S a y f a
Yukarıda yaptığımız iki farklı servis aynı işlemi yapmaktadır. Ama bu işlemlerin ikisinide gerçekleştirmek için farklı yapılarda farklı projeler oluşturmamız gerekiyordu. Yazılımcı için bir kod tekrarı ve zaman kaybı söz konusuydu. Bunun dışında servisde bir güncelleme yapıldığında iki farklı projede bu güncellemeyi düzenlememiz gerekiyordu.
Ama WCF ile birlikte gelen end point mantığı ile birlikte sadece bir kaç dakikalık bir konfigurasyon ile .Net Remoting ile hazırladığımız projeyi XML Web Service projesine çevirebiliyoruz.
7.2.1. WCF Çatısı Altında Toplanan Modeller .Net Remoting XML Web Servisleri COM+ ve MSMQ 7.2.1.1. XML Web Services XML mesajlaşma tabanlı bir sistem entegrasyon yöntemidir. W3C tarafından yapılan resmi tanımıyla web servisi, bilgisayarlar arasında ağ üzerinden etkileşimi ve uyumluluğu sağlayacak yazılım sistemidir.
Web servisi, XML tabanlı mesajlaşmayı esas alır. Bu nedenle, eski entegrasyon sistemlerinin aksine, haberleşecek sistemlerin birbirlerinden haberdar olması veya platformlarının uyumlu olması gerekmez. Örneğin, Java ile geliştirilmiş ve UNIX sistem üzerinde çalışan bir uygulama ile .NET ile geliştirilmiş ve Windows işletim sistemi üzerinde çalışan bir uygulama, birbirlerinin çalışma ortamlarından bağımsız olarak, XML iletişim standartları aracılığıyla iletişim kurabilir. Web servisinin en büyük faydası budur.
XML Web Servisleri farklı platformalar arasında ortak olarak kullanılabilen bileşenlerdir. XML Web Servisleri ile farklı platformlar arasında veri aktarmada belli standartlar sayesinden oldukça kolaylaşmaktadır. XML Web Servisleri standart olan protokoller üzerinde çalışır. Bunlar, HTTP, XML, SOAP standartlardır. XML Web Servisleri adından da anlaşıldığı gibi mesaj alış verişi için XML standardını kullanır.
XML’ in bir standart olması ve herhangi bir platforma bağlı olmaması sayesinde XML Web Servisleri farklı platformların konuşmasını, veri alış verişini sağlar. Bu sayede uygulama geliştirme aşamasında programcılar farklı sistemleri kullanan uygulamalar yazarken standartları kullanarak işlerini daha kolay bir şekilde yapabilirler.
189 | S a y f a
7.2.1.2. .Net Remoting Uzak bağlantı kurmak için kullanılır. Uzak bir bilgisayara bağlanır, çeşitli komutlar gönderip cevap vermesini sağlayabiliriz. Bu komutlar cd sürücüsü açmak, ekran görüntüsü paylaşmak gibi işlemler yapılabilir. Remoting; yazılımcılara dağıtık uygulama oluşturma imkanı sunar. Nesne, karşı tarafta etkileşimde bulunacağı nesneden transfer edilen mesajlara cevap vermek için kanallar kullanır. TCP protokolü ile paylaşım yapar. 7.2.1.3. Microsoft Message Queuing Microsoft Message Queue(MSMQ), Windows NT sürümünde gelen bir bileşendir. MSMQ değişik zamanlarda birbirinden bağımsız olarak çalışan uygulamalar veya sistemler arasında veri transferi yapılabilmesini sağlayan bir teknolojidir. MSMQ , sistemler arasında sürekli bir bağlantı gerektirmemektedir. Bu da sistemlerin asenkron olarak yüksek performanslı ve veri kaybı olmaksızın çalışmalarını sağlar.
TCP veya HTTP bazlı iletişimlerde, tarafların aynı zaman dilimi içerisinde çalışıyor olmaları gerekmektedir. Böyle bir mesajlaşma sürecinde taraflardan herhangibirin çalışmaması, aradaki bağlantının kopması gibi nedenlerden dolayı tüm iletişimin aksamasıda muhtemeldir.
Bazı gerçek hayat senaryolarında, sistemin tarafları olan istemci, sunucu, ağ bileşenlerinin çökmesi durumlarında dahi işlevselliğin devam edebilmesi istenebilir. Bunun dışında, çalışan sistemin içerisindeki bileşenlerin sürekli bir bağlantıda olmadığı durumlarda bu tip iletişimleri zorlaştırmaktadır. Bir başka deyişle ağa sürekli olarak bağlanamayan ama offline olarak çalışabilen istemcilerin bu tip bir mesajlaşma sisteminin parçası olması istendiğinde senkronizasyon güçlükleri ortaya çıkmaktadır.
7.2.1.4.
COM+ (Component Object Model) COM, programlama dilinden bağımsız, program parçacıkları geliştirmek için belirlenen standartlar topluluğudur.
COM+, COM teknolojisinin ikinci jenerasyonudur. COM teknolojisine yeni özellikler eklenerek dağıtık yapıda sınıflar içeren uygulamaların geliştirilmesi kolaylaşmıştır.
7.3. Genel Kavram ve Terimler 7.3.1. Message Veri parçalarının birbirinden bağımsız hali olan paketlerdir, başlık (header) ve gövde (body) dahil olmak üzere bölümlerden oluşmaktadır. Bir mesajın başlık dışında, tüm parçaları şifreli ve dijital imzalanmış olabilir.
190 | S a y f a
7.3.2. Service
Bir servis modülünün ‘n’ tane endpoint desteği vardır. Her endpoint n tane servis işlemi yapmanıza olanak sağlar.
7.3.3. Endpoint İstemci ve Servis arasındaki iletişimi sağlamak için kullanılan bağlantı noktasıdır. Her endpoint’in kendi adresi bulunur. Bir WCF servisini endpoint topluluğu olarak düşünebiliriz.
7.3.4. Binding
Endpoint’in dış dünya ile nasıl haberleşileceğinin tanımlandığı bir takım özellikler bütünüdür. Yani endpoint ile iletişimin (HTTP, TCP veya SOAP) nasıl yapılacağının tanımlandığı noktadır. Bir binding ile endpoint‘in kullanacağı security yada message pattern gibi detayları ayarlanabilmektedir.
7.3.5. Service Contract
Contract servisin adının, namespace’inin ve diğer global niteliklerinin tanımlandığı bileşendir. Uygulamalarımızda Contract, bir interface oluşturularak bu interface’e [Service Contract] attribute’u eklenilerek kullanılmaktadır.
7.3.6. Operation Contract
[ServiceContract] etiketi uygulanılarak oluşturulmuş interface’in içerisinde bulunan metodların (operasyonların) servis tarafında kullanılabilmesi için uygulanan etikettir. Interface içerisindeki metodlara [OperationContract] etiketi uygulanarak kullanılır. Bu attribute o metodun servisin bir parçası olacağı anlamına gelir.
7.3.7. Data Contract
Servisi kullanan istemciler ile ortak çalışmayı sağlamak için servisin kullandığı veri nesneleri hakkında bilgi veren veriler olarak tanımlanabilir.
7.3.8. Host
Genelde servisin yaşam süresini kontrol etmek amacıyla kullanılan bileşendir.
7.3.9. Behaviour
Servisin çalışma zamanındaki fonksiyonelliğini zenginleştirerek gerekli parametrik ayarların yapıldığı bir tipdir.
191 | S a y f a
7.3.10. System-provided bindings
Bazı senaryolar için optimize edilmiş binding topluluğudur.
Genel kavram ve terimleride öğrendiğimize göre, bir WCF projesi geliştirmeye başlayabiliriz.
7.4. Windows Communication Foundation Örneği
Visual Studio’da yeni bir proje oluşturuyoruz. Daha önce Windows Form Application ve Class Library projeleriyle çalışmıştık. Yeni proje penceresinden “WCF Service Library” projesi oluşturuyoruz. WCF, standart olarak kullandığımız Class Library gibidir. Class Library’den farklı servis mimarisi için gerekli kütüphaneler referanslarına tanımlı olarak gelmektedir. Bu kütüphaneler;
System.Runtime.Serialization System.ServiceModel
Projemizin adını WCFSample olarak belirleyelim.
192 | S a y f a
WCF Projesini oluşturduğumuzda karşımıza WCF ile ilgili yapılar çıkacaktır. Bu yapılar WCF’in çalışma mantığı hakkında bilgiler vermektedir. Biz burada bulunan hazır classları kullanmayacağımız için solution explorer içerisinde bulunan Service1 classını ve IService interface’ini siliyoruz.
Daha sonra projemize yeni bir class ve interface ekliyoruz. Class adını “Servisim.cs”, interface adını ise “IServisim.cs” olarak belirleyerek tekrardan oluşturuyoruz. Class ve Interface dosyamızı oluşturduktan sonra App.config dosyasında bir düzenleme yapmamız gerekmektedir aksi taktirde hata alırız. Aşağıdaki değişikliği app.config dosyasında yapalım..
App.config içerisinde yukarıda ki satırı buluyoruz, ve aşağıda ki satır ile değiştiriyoruz.
Bu işlemi yaptıktan sonra aşağıdaki değişiklikleride yapmamız gerekmektedir.
Tekrar yukarıda ki satırı bulun ve aşağıdaki şekilde kodu düzenleyiniz.
193 | S a y f a
End point sonunda bulunan “IService1” bilgisini “IServisim” ismiyle oluşturduğum interface ile değiştirdim. Burada bulunan end point yazdığımız servisin hangi yol ile (.Net Remoting, Http Web Service vb.) yayına açılacağını belirler.
Yukarıda bir adet class ve interface kullandık, işte tam burada çok önemli bir bilgi paylaşmamız gerekiyor. Servise açılacak metotlar interface içerisinde tanımlanır. Tanımladığımız metotlar class’a implament edildikten sonra gövdesi doldurulur.
Interface’imiz içerisinde bir metot belirliyoruz. Oluşturacağımız metot, servise göndereceğimiz iki sayıyı toplayıp, sonucunu bize geri gönderecek. Aşağıdaki metodu IServisim.cs içerisinde tanımlayalım.
IServisim.cs interface IServisim { int SayiTopla(int sayi1, int sayi2); }
Yukarıda metodumuzu interface içerisinde tanımladık. Hatırlayacağınız üzere interface içerisinde belirlenen yeteneklerde erişim belirteci (access modifiers) kullanmıyorduk. Ayrıca oluşturduğumuz metodun gövdesini oluşturmuyorduk. Interfaceler ile ilgili ufak bir hatırlatmadan sonra servis yapısına geçelim.
Servis mimarisinde, sözleşmeler üzerinden hareket edilir. Bizim oluşturduğumuz interface dosyasının ve içerisinde oluşturduğumuz operasyonların (method) servise açılacağını bildirmemiz gerekiyor. Bu bildirimler, attributelar ile işaretlenerek yapılır. Bir metodu, servis operasyonu haline getirebilmek için, içerisinde yer alan interface’i [ServiceContract], içerisinde bulunan metodu ise [OperationContract] olarak işaretlemeliyiz.
Yukarıdaki interface’imizde aşağıdaki düzenlemeleride yapalım.
IServisim.cs [ServiceContract] //Interface'in servise açılacağını belirledik. interface IServisim { [OperationContract] //Bu metodun servisin bir operasyonu olduğunu belirledik. int SayiTopla(int sayi1, int sayi2); }
Dosyamızı implament ettikten sonra metod gövdesini aşağıdaki gibi dolduralım.
Servisim.cs > SayiTopla(int sayi1, int sayi2) Public class Servisim : IServisim { public int SayiTopla(int sayi1, int sayi2) { return sayi1 + sayi2; } }
Metodumuzun içeriğini hazırladık. Daha önce WCF projesinin aslında bir Class Library olduğundan bahsetmiştik. Hatırlacağınız üzere OOP’de Class Library projelerinin çalıştırılabilir (Executible) olmadığını anlatmıştık. Bu durum proje içerisine eklenen kütüphanelerden dolayı WCF projesi için geçerli değildir. WCF projesini çalıştırdığımızda “WCF Test Client” adında bir test ekranı açılacaktır. Bu test ekranını kullanarak servisimizin içerisinde yazdığımız operasyonların çalışıp çalışmadığını test edebiliriz.
195 | S a y f a
Metodumuzun üzerine çift tıklıyoruz. Aşağıda açılan pencere yardımıyla metodumuzu test ediyoruz.
Aşağıdaki resimde test ekranıyla ilgili detaylı bilgileri görebilirsiniz. Name kolonunda istenilen parametrelerin isimleri bulunmaktadır. Value kolonunda ise bu parametre gönderilecek olan verileri girebiliriz. Eğer parametre almayan bir servis operasyonu tanımladıysak, parametre ekranında bir bilgi girişi istemeyecektir.
Type kolonunda ise, parametre olarak göndermemiz gereken bilgilerin veri tipleri bulunmaktadır. Burada bulunan veri tipleri metod içerisinde belirlediğimiz parametrelerin veri tipleridir.
196 | S a y f a
7.4.1. SOAP Nedir
SOAP (Basit Nesne Erişim Protokolü) dağıtık uygulamalarda ve web servislerinin haberleşmesinde kullanılmak üzere tasarlanan, istemci/sunucu mantığına dayalı bir protokoldür.
Metot Çağırımı Cevap Mesajı Hata Mesajı
7.4.2. HTTP Nedir Http bir kaynaktan dağıtılan ve ortak kullanıma açık olan hiperortam bilgi sistemleri için uygulama seviyesinde bir iletişim kuralıdır.
7.4.3. TCP Nedir
TCP (Transmission Control Protocol), TCP/IP protokol takımının iki aktarım katmanı protokolünden birisidir.
197 | S a y f a
7.4.4. WCF Binding
198 | S a y f a
199 | S a y f a
WINDOWS AZURE 8.1. Windows Azure Nedir?
Windows Azure, Microsoft’un Genel Bulut Uygulama ve alt yapı platformudur. Bu platformu pek çok şekilde kullanabilme imkânına sahibiz. Örnek olarak Azure ile verilerini Microsoft veri merkezleri üzerinden çalıştıran ve saklayan bir internet uygulaması hazırlayabilirsiniz. Windows Azure’u, verileri kurum içerisinde (yani genel bulut dışında) kullanan uygulamalar için sadece veri depolamak amacıyla da kullanabilirsiniz. Windows Azure’u geliştirme ve test işlemleri veya SharePoint ve diğer uygulamaları çalıştırmak amacıyla sanal makineler oluşturmak için de kullanabilirsiniz. Windows Azure’u çok ama çok sayıda kullanıcıya sahip çok büyük ölçeklendirilebilir uygulamalar oluşturmak için de kullanabilirsiniz.
200 | S a y f a
Platform pek çok hizmet sunduğundan tüm bunlar ve çok daha fazlası mümkündür. Bunlardan herhangi birisini gerçekleştirebilmek için temel bilgileri anlamanız gerekmektedir. Bulut bilişimi – NIST (ABD Ulusal Standartları ve Teknoloji Enstitüsü) ise şu şekilde tanımlanmaktadır; ”Bulut bilişim, düşük yönetim çabası veya servis sağlayıcısı etkileşimi ile hızlı alınıp salıverilebilen ayarlanabilir bilişim kaynaklarının paylaşılır havuzuna, istendiğinde ve uygun bir şekilde ağ erişimi sağlayan bir modeldir.”
Bulut bilişim çeşitlerine bakıldığında 4 temel yapının çıktığı görülmektedir; Public Cloud; İnternet üzerindeki sunucular ile verilen cloud hizmetidir. Private Cloud: Şirket bünyesinde oluşturulmuş sunucular ile verilen bulut hizmetidir. Community Cloud; Burada bulut bilişim alt yapısı belirli kurum ve ortak hareket eden kuruluşlar tarafından paylaşılmaktadır. Topluluk üyeleri uygulama ve verilere erişebilmektedir. Hybrid Cloud; Bir şirketin verilerin güvenliği ve benzeri nedenlere göre hem public hemde private cloud kullanması ile ortaya çıkan yapıdır.
201 | S a y f a
8.2. Windows Azure’ un Bileşenleri
Şekil 1: Windows Azure, Microsoft veri merkezleri üzerinde çalışan, internet üzerinden erişilebilir uygulama hizmetleri sunmaktadır.
202 | S a y f a
8.3. Bulut Bilişim
8.3.1. IAAS ( Infrastructure ) Infrastructure As A Service yapısında, altyapı Microsoft tarafından bize servis olarak sağlanıyor. Network ayarları ve yönetimi, disk seçimi, sunucu yönetimi ve sanallaştırma gibi yapılar Microsoft tarafından yönetilir.
8.3.2. PAAS ( Platform ) Platform As A Services seçeneğinde, IAAS yapısına ek olarak işletim sistemi, runtime ve sql gibi yapılar kurulu gelmektedir. Buna ek olarak altyapının bakımı ve yönetimi gibi konularda sağlayıcı tarafından sağlanıyor. Sunucu alımı, network ayarlanması, yönetilmesi, sanallaştırılması, işletim sistemi lisans alınması ve işletim sisteminin ayarlanması, runtime kurulumları yapıp güvenlik ayarları yapılması ve patch yönetimini gibi konularda yönetim tamamen sağlayıcı tarafından yapılmaktadır.
8.3.3. SAAS (SoftWare) Software As A Services modelinde, tüm yapı tamamiyle sağlayıcı tarafından sağlanmaktadır. Buna örnek olarak hotmail ve gmail gibi yapıları örnek verebiliriz. Tüm yapı sağlayıcı tarafından yönetilir.
203 | S a y f a
8.4. Güvenlik
24 saat izlenen fiziksel güvenlik Verilerin ve hizmetlerin yetkisiz erişim ve çevresel tehditlere karşı korunması için fiziksel olarak veri merkezleri oluşturulur, yönetilir ve izlenir.
İzleme ve günlüğe kaydetme Güvenlik, ortamdaki cihazların ürettiği büyük miktarda bilgiyi yöneten ve zamanında uyarılar sağlayan merkezi izleme, bağıntı ve analiz sistemlerinin yardımıyla izlenir. Ayrıca, kullanıcılara görünürlük sağlamak için birden fazla düzeyde izleme, günlüğe kaydetme ve raporlama kullanılabilir.
Düzeltme Tümleşik dağıtım sistemleri yüklenmesini yönetir.
güvenlik
düzeltme
eklerinin
dağıtımını
ve
Kullanıcılar, Azure' da dağıtılan Sanal Makineler için benzer düzeltme eki yönetim süreçlerini uygulayabilir.
Virüsten/Kötü amaçlı yazılımdan korunma Microsoft Kötü Amaçlı Yazılımdan Korunma, Bulut Hizmetleri'nde yerleşiktir ve virüslerin, casus yazılımların ve diğer kötü amaçlı yazılımların belirlenmesi ve kaldırılmasına yardımcı olmak ve gerçek zamanlı koruma sağlamak amacıyla Sanal Makineler için etkinleştirilebilir.
204 | S a y f a
Kullanıcılar aynı zamanda Sanal Makinelerinde bulunan iş ortaklarının kötü amaçlı yazılımdan korunma çözümlerini de çalıştırabilirler.
Yetkisiz giriş algılama ve DDoS Yetkisiz giriş algılama ve önleme sistemleri, hizmet reddi saldırısından korunma, düzenli sızma testi ve forensic araçları Azure' un hem dışından hem de içinden gelen tehditlerin belirlenmesine ve azaltılmasına yardımcı olur.
Kalıcı sıfır ayrıcalık Microsoft operasyon ve destek personelinin kullanıcı verilerine erişimi varsayılan olarak reddedilir. İzin verildiğinde, erişim dikkatli bir şekilde yönetilir ve günlüğe kaydedilir. Kullanıcı verilerini depolayan sistemlere veri merkezi erişimi, kasa işlemleriyle sıkı bir şekilde de denetlenir.
İzolasyon Azure dağıtımlar arasında istenmeyen iletişimlerin oluşmasını önlemek için ağ izolasyonu kullanır ve erişim denetimleri yetkisiz kullanıcıları engeller. Sanal Makineler, müşteriler yapılandırmadığı sürece Internet'ten gelen trafik alamaz.
Azure Sanal Ağları Müşteriler, izole edilmiş bir Sanal Ağa birden fazla dağıtım atamayı ve bu dağıtımların özel IP adresleri aracılığıyla birbirleriyle iletişim kurmasına izin vermeyi seçebilir.
Şifreli iletişimler Yerleşik SSL ve TLS şifrelemesi, kullanıcıların Azure'dan şirket içi veri merkezlerine ve Azure'dan yöneticilere ve kullanıcılara yapılan dağıtımlar içindeki ve arasındaki iletişimleri şifrelemesini sağlar.
Özel bağlantı Kullanıcılar Azure veri merkezleriyle özel bir bağlantı kurup trafiklerini Internet dışında tutmak için ExpressRoute'u kullanabilir.
Veri şifreleme
205 | S a y f a
Azure AES-256'ya kadar çok çeşitli şifreleme özellikleri sağlar ve kullanıcı ihtiyaçlarına en uygun yöntemleri uygulama esnekliğini sunar.
Kimlik ve erişim Azure Active Directory, kullanıcının Azure, Office 365 ve diğer bulut uygulamaları dünyasına erişimi yönetmesini sağlar. Multi-Factor Authentication ve erişim izleme gelişmiş güvenlik sağlar. Sızma Testi Microsoft Azure güvenlik denetimlerini ve süreçlerini iyileştirmek için düzenli olarak sızma testleri yapmaktadır. Kullanıcıların Azure’ da barındırılan uygulamaları üzerinde yetkili sızma testleri gerçekleştirebilmektedirler. Bu testleri gerçekleştirmek isterseniz Azure Müşteri Desteğinden onay almanız gerekmektedir.
8.5. Yüksek Performans Bir bulut platformunun dikkat çeken yönlerinden birisi yüksek performanslı bilişim (HPC) gücüdür. HCP’ nin temel yapısında aynı kodları, aynı anda birden fazla makine üzerinde çalıştırabilmesi yatmaktadır. Windows Azure üzerinde karşılaşılan problemleri çözmek için pararel olarak görev alan eş zamanlı çok sayıda sanal makinenin çalıştırılmasıdır. Bunu yapmak için bir şekilde uygulamaları programlamak gerekir, yani yapılacak işi bu örnekler arasında dağıtmak gerekir. Windows Azure bunu yapmak için HPC Scheduler'ı kullanır. Bu bileşen, sektör standardı Message Passing Interface'i (MPI) kullanmak üzere tasarlanmış HPC uygulamalarını kullanabilmektedir. Araba çarpışma simülasyonları gibi sınırlı analiz yapmayan yazılımlar bu tür bir uygulamalardan pek çoğuna örnek olarak gösterilebilir. HPC Scheduler ayrıca Monte Carlo simülasyonları gibi sıkıcı paralel olarak adlandırılan uygulamalarla da kullanılabilir.
206 | S a y f a
Hangi problem üzerinde çalışılırsa çalışılsın sağlayacağı değer aynıdır: HPC Scheduler, birçok Windows Azure sanal makinesi üzerinde paralel bilişim programlaması gibi karmaşık bir sorunu çözer. Burada amaç bulut üzerinde çalışan HPC uygulamalarını oluşturmayı daha kolay bir hale getirmektir.
8.6. Grid Computing
Distributed computing olarak adlandırılan dağınık bilgi işleme yönteminin sanallaştırılmasını sağlayan çözüm mimarisine kısaca Grid Computing denilmektedir. Grid Computing açık standart ve protokoller ile kurulan, genel iş hedeflerine göre belirlenmiş dağıtık ve sanal bir yapıdır. Burdaki temel amaç, dağıtık bilgi işleme ve veri kaynaklarının kullanıldığı işlemciler, ağ ve depolama ürünleri ile tek ve büyük bir sistem yaratmaktır. Yaratılan bu sistem tamamen birbirinden bağımsız çalışmakta olan ve birbirine benzemeyen sistemlerin bir araya gelerek oluşturduğu sanal bir işleme gücüdür.
207 | S a y f a
8.7. Sanal Makineler
İster standart ister sizin sunacağınız bir imaj ile talep tabanlı sanal makine oluşturma yeteneği çok yararlı olabilir. Bu sanal makinenin saat başı ücretlendirilebilmesi ise daha da yararlıdır. Windows Azure Virtual Machines de genelde Hizmet olarak Altyapı (IaaS) olarak tanımlanan bu yaklaşımı size sunar. Bir VM (Sanal Makine) oluşturabilmek için hangi VHD'nin kullanılacağı ve VM boyutlarını belirtmeniz gerekir. Bunun ardından VM'in çalıştığı her saat için ücret ödersiniz. Şekil 2'de de gösterildiği gibi Windows Azure Virtual Machines standart VHD’lerden oluşan bir galeri sunmaktadır. Bunlar içerisinde Windows Server 2008 R2, Windows Server 2012 ve SQL Server ile Windows Server 2008 R2 gibi Microsoft tarafından sunulan seçenekler ve ayrıca Microsoft iş ortakları tarafından sunulan Linux imajları yer alır. Ayrıca kendi VHD’lerinizden de VM'ler yükleme ve oluşturma imkânına sahip olursunuz.
208 | S a y f a
İmaj nereden gelirse gelsin bir VM çalışırken yapılan değişiklikleri kalıcı bir şekilde kaydedebilirsiniz. Aynı VHD'den bir daha bir VM oluşturduğunuzda kaldığınız yerden de devam edebilirsiniz. Ayrıca değiştirilen VHD'yi Windows Azure dışına kopyalamak ve yerelde çalıştırmak mümkündür.
Windows Azure VM'leri çok farklı şekillerde kullanılabilir. Pahalı olmayan bir geliştirme ve test platformu oluşturmak ve kullanmayı bitirdiğinizde de kapatmak için kullanabilirsiniz. Aynı zamanda istediğiniz dilleri ve kütüphaneleri kullanan uygulamaları oluşturmak ve çalıştırmak da mümkündür. Bu uygulamalar Windows Azure tarafından sağlanan her türlü veri yönetimi seçeneğini kullanabilmektedir. Ayrıca bir veya daha fazla makine üzerinde çalıştırabileceğiniz SQL Server veya diğer DBMS'yi kullanmayı da seçebilirsiniz. Diğer seçenek ise Windows Azure'u SharePoint veya diğer uygulamaları çalıştıran kurum içi veri merkezinizin bir uzantısı olarak kullanmaktır. Bunun için Windows Azure VM'leri içerisinde Active Directory'yi çalıştırarak bulut üzerinde Windows etki alanları yaratmak mümkündür. Bulut bilişim için bu genel yaklaşım pek çok farklı problemi çözmek amacıyla kullanılabilir. Hangisini seçeceğiniz size bağlı.
8.8. Veri Yönetimi
209 | S a y f a
8.8.1. SQL Database Windows Azure ilişkisel depolama için SQL Database'i sağlar. Buna atomik işlemler, verilere birden çok kullanıcı tarafından eş zamanlı erişim ve veri bütünlüğü, ANSI SQL sorguları ve bilinen bir programlama aracı da dahildir. SQL Server gibi, SQL Database'e de Entity Framework, ADO.NET, JDBC ve diğer bilinen veri erişimi teknolojileri ile erişilebilir. Ayrıca T-SQL dilinin büyük bir kısmı ve SQL Server Management Studio gibi SQL Server araçları da desteklenir. SQL Server (veya bir başka ilişkisel veri tabanı) kullanımını bilen herhangi birisi için SQL Database'in de kullanımı basittir. Fakat SQL Database sadece bulut içerisindeki bir DBMS değil bir PaaS hizmetidir. Halen daha verilerinizi ve verilerinize kimin eriştiğini siz kontrol edersiniz fakat SQL Database, donanım altyapısını yönetmek ve veri tabanını ve işletim sistemini güncel tutmak gibi yönetim işlerinin büyük kısmını sizin adınıza yapar. SQL Database ayrıca verileri birden çok sunucuya dağıtan federasyon seçeneği de sunmaktadır. Bu seçenek çok büyük verilerle çalışan veya daha iyi performans için veriye erişim taleplerini birden çok sunucu arasında dağıtması gereken uygulamalar için yararlıdır. Üç çalıştırma modelinden birisini kullanarak Bir Windows Azure uygulaması oluşturuyorsanız ve oluşturduğunuz uygulama ilişkisel depolama gerektiriyorsa SQL Database iyi bir seçenek olabilir. Bulut dışında çalışan uygulamalar da bu hizmeti kullanabilir fakat bu konuyla ilişkili daha birçok senaryo vardır. Örneğin SQL Database üzerinde saklanan verilere masaüstü, dizüstü, tablet bilgisayarlar ve telefon gibi farklı istemci sistemlerinden erişilebilir. Çoğaltma sayesinde dahili olarak yüksek kullanılabilirlik sağladığı için SQL Database aksama sürelerini azaltmaya da yardımcı olur. 8.8.2. Tables Yazılı verilere hızlı erişim gerektiren bir Windows Azure uygulaması oluşturmak istiyorsunuz ve diyelim ki bu veriler büyük boyutlarda fakat bu veriler üzerinde karmaşık SQL sorgularının yapılması gerekmiyor. Örneğin her bir kullanıcının müşteri profil bilgilerini saklayacak bir tüketici uygulaması hazırladığınızı varsayalım. Uygulamanız çok popüler olacak bu yüzden büyük ölçekte veriye izin vermeniz gerekecek fakat bu veriler saklamakta ve basit yöntemlerle geri çağırtmaktan daha fazla bir şey yapmayacaksınız.
210 | S a y f a
Bu da tam Windows Azure Tables'ın kullanılabileceği bir alandır. İsmi sizi şaşırtmasın bu teknoloji ilişkisel depolama sunmuyor. (aslında anahtar/değer depolama olarak adlandırılan bir NoSQL yaklaşımı). Buna karşın Windows Azure Tables, dize, bilgi ve tarihler gibi bir uygulamanın çeşitli türlerdeki özellikleri saklamasına izin veriyor. Uygulama da grupla ilişkili özgün bir anahtar sunarak o grubun özelliklerini elde edebiliyor. Birleştirme gibi karmaşık işlemler desteklenmese de tablolar yazılı verilere hızlı erişim sağlıyor. Aynı zamanda son derece ölçeklendirilebilirdir ve tek bir tablo bir terabayt kadar veriyi tutabiliyor. Basitliğine ilave olarak tabloların kullanımı SQL Database'in ilişkisel depolamasını kullanmaktan daha da ucuz.
8.8.3. Blob Storage Tables gibi Blobs da pahalı olmayan depolama sağlar ve tek bir blob bir terabayt büyüklüğünde olabilir. Örneğin videolar veya yedekleme verileri veya diğer ikili bilgileri saklayan bir uygulama basit ve ucuz depolama için Blobs'u kullanabilir. Windows Azure uygulamaları ayrıca Windows Azure sürücülerini de kullanabilir ve bu sayede Blobs bir Windows Azure örneği üzerine takılmış olan Windows dosya sistemi için kalıcı depolama sağlar. Uygulama sıradan Windows belgelerini görür fakat içerikleri gerçekte bir blob içerisinde saklanır.
8.9. Web Sitesi
211 | S a y f a
Internet Information Services'ın (IIS) kullanıldığı bu modelde yönetilen bir internet ortamı sunulur. Mevut bir IIS internet sitesini Windows Azure Web Sites üzerine değiştirmeden taşıyabilir veya bir yenisini direkt bulut üzerinde oluşturabilirsiniz. Bir internet sitesi çalıştığında örnekleri dinamik olarak ekleyebilir veya kaldırabilir ve bu sırada taleplerle ilişkili yüklerin dengelenmesi işini Web Sites'a bırakabilirsiniz. Windows Azure Web Sites hem geliştiriciler hem de internet tasarımı işi yapan ajanslara yarar sağlaması amaçlanmıştır. Geliştirme açısından, ilişkisel depolama için SQL Database ve (bir Microsoft ortağı olan ClearDB ile) MySQL'e ilave olarak .NET, PHP ve Node.js, desteği sunuyor. Ayrıca WordPress, Joomla ve Drupal de dahil olmak üzere çeşitli popüler uygulamalara dahili destek de mevcut. Amaç internet sitelerinin ve uygulamalarının genel bulut üzerinde oluşturulması için düşük maliyetli, ölçeklendirilebilir ve büyük ölçüde yararlı bir platform sunmaktır.
8.10. Ağ İletişimi
212 | S a y f a
Windows Azure ABD, Avrupa ve Asya’ da bulunan veri merkezlerinde çalışıyor. Bir uygulama çalıştırdığınızda veya veri depolama işlemi gerçekleştirdiğinizde kullanmak istediğiniz bir veya birden fazla veri merkezi seçebiliyorsunuz. Bu veri merkezlerine bağlanmak için farklı yöntemler kullanabilirsiniz;
Kendi kurum içi yerel ağınızı belirli Windows Azure VM’ lerine bağlamak için Azure Virtual Network’ ü kullanabilirsiniz.
Bir veya birden fazla Windows sunucusunu belli bir Windows Azure uygulamasına bağlamak için Windows Azure Connect’ ten yararlanabilirsiniz.
Windows Azure uygulamanız birden çok veri merkezinde çalışıyorsa kullanıcılardan gelen talepleri akıllı bir şekilde uygulamanın örnekleri arasında yönlendirmek için Windows Azure Traffic Manager’ ı kullanabilirsiniz.
8.10.1. Virtual Network Bir VPN ağ geçidi aygıtı kullanan bir yönetici, yerel ağınız ve Windows Azure üzerinde çalışan belirli bir grup VM arasında bir sanal özel ağ (VPN) oluşturabilir. Bulut VM' lerine kendi IP v4 adreslerinizi atayacağınız için kendi ağınız üzerinde görüneceklerdir. Bu sayede işletmenizdeki kullanıcılar VM' ler içerisindeki bu uygulamalara yerelde çalışıyormuşcasına erişecektir.
8.10.2. Connect Connect, bir Windows Azure uygulaması ve Windows çalıştıran bir grup bilgisayar arasında güvenli bir bağlantı kurmak için basit bir yol sunar. Geliştirici sadece Connect yazılımını kurum içi bilgisayarlara kurar (ve bu durumda bir ağ yöneticisine ihtiyaç kalmaz) ve Windows Azure uygulamasını yapılandırır. Bu işlem tamamlandıktan sonra uygulama sanki aynı ağ üzerindeymiş gibi kurum içerisindeki bilgisayarlarla iletişime geçebilir.
213 | S a y f a
8.10.3. Traffic Uygulamanın sahibi kullanıcı taleplerinin veri merkezlerine nasıl yönlendirileceği konusundaki kuralları belirler ve ardından Traffic Manager bu kuralları uygular. Örneğin kullanıcılar en yakın Windows Azure veri merkezine yönlendirilebilir fakat varsayılan veri merkezinin tepki süresi belirlenmiş bir eşiğin altında kaldığında bir başka veri merkezine yönlendirilir. Küresel olarak dağıtılmış ve çok sayıda kullanıcıya sahip uygulamalarda bu gibi sorunların çözülmesi için dâhili bir hizmete sahip olmak yararlıdır.
8.11. Kimlik
Çoğu uygulamanın yaptığı işler arasında kimlik ile çalışmak yer alır. Örneğin bir kullanıcının kim olduğunu bilmek uygulamanın o kullanıcı ile nasıl etkileşime geçeceğine karar vermesine imkân verir. Bunun için Microsoft, Windows Azure Active Directory'i sunuyor. Çoğu dizin hizmeti gibi Windows Azure Active Directory kullanıcılar ve kullanıcıların bağlı oldukları kuruluşlar hakkında bilgileri saklamaktadır. Kullanıcıların bağlanmasına izin vermekte ve ardından kimliklerini kanıtlamak için uygulamalara sunabilecekleri belirteçler sağlamaktadır. 214 | S a y f a
Ayrıca kullanıcı bilgilerinin, kurum içerisindeki yerel ağınızda çalışan Windows Server Active Directory ile eşitlenmesine izin vermektedir. Windows Azure Active Directory tarafından kullanılan mekanizmalar ve veri formatları Windows Server Active Directory tarafından kullanılanlarla aynı olmasa da yerine getirdiği fonksiyonlar son derece benzerdir.
8.12. Medya
Gelişen teknoloji ve sosyal ağların çoğalması gibi faktörlerden dolayı internet trafiğinin çoğunu videolar oluşturmaktadır. Sıkıştırma algoritmaları ve kullanıcı ekranındaki görünüm çözünürlüğü gibi birçok faktör bulunmaktadır. Sürekli değişiklik gösteren internet trafiğinden etkilenmemek için ve yoğunluk anlarında uygulamamızın performanslı çalışıp kullanıcıların ihtiyaçlarını karşılamak için medya servisinden yararlanabilirsiniz.
8.13. Uygulamalar
Sanal Makine:
Portal’ a giriş yaptıktan sonra, “VIRTUAL MACHINES” ya da sol alt tarafta bulunan “NEW” seçeneğini tıklayarak sanal makine oluşturma işlemine başlayabilirsiniz.
215 | S a y f a
216 | S a y f a
Karşımıza çıkan seçenekler’ den “QUICK CREATE” seçeneğine tıkladıktan sonra ilgili alanları doldurduktan sonra hızlı bir şekilde sanal makinemizi oluşturabiliriz.
Diğer seçenek olan “FROM GALLERY” kısmı ise bize birden fazla seçenek sunar. Bu seçenek bize diğer işletim sistemleri kurulu sanal makinelerle çalışma imkânı sunar ve buna ek olarak kendi imajımızı yükleyerek çalışma ortamı sunmaktadır. Bu adımda çalışmak istediğimiz sanal makineyi seçiyoruz. Buradaki işlemler bittikten sonra bir sonraki adıma geçiyoruz.
Sonraki adımda makinemizin yapılandırma ayarlarını seçiyoruz. Kullanacağımız makinemize isim verdikten sonra donanım yapısını seçip, makinemize bağlanmak için yeni bir kullanıcı adı ve şifresi seçip bir sonraki adıma geçiyoruz.
217 | S a y f a
Bu adımda ise makinemiz için tanımlı bir bulut servisi varsa seçebiliriz. Makinemiz için Dns ismi belirledikten sonra makinenin tutulacağı datacenter lokasyonu ve storage ayarlarını yaptıktan sonra diğer adıma geçiyoruz.
218 | S a y f a
Kurulum aşamasındaki son adım da ise yapılandırma ve güvenlik için ek olarak sunulan eklentileri seçip makinemizi oluştura biliriz.
Bu adımda sanal makinemiz oluşmakta.
219 | S a y f a
Sanal makinemiz seçtiğimiz ayarlar doğrultusunda oluşmuş ve kullanım için hazırdır. Alt menü’ den “CONNECT” e tıklayarak makinemize bağlanabiliriz.
220 | S a y f a
Gelen ekranda bağlantıyı onaylayarak makinemizi kullanmaya başlayabiliriz.
Giriş yaptıktan sonra makinemizi kullanmaya başlayabiliriz.
221 | S a y f a
8.14. Active Directory
Kimlik bölümünde açıkladığımız gibi uygulamalarınızı yönetebileceğiniz, sosyal medya hesaplarınız gibi birçok hesabı tek bir yerden yönetebileceğiniz bir yapıdır. Sosyal medya hesaplarımızı tek bir yerden yönetmeyi adım adım başlatalım. İlk olarak Active Directory kısmından varsayılan (kullanıcı hesabı) olan bölüme çift tıklayarak hesap yönetim sayfasına giriş yapıyoruz.
222 | S a y f a
Bu bölümde yeni kullanıcılar ekleyip gruplar oluşturabilir ve kullanıcılara uygulamalar ekleyebilirsiniz. Bu bölümde Application sekmesine tıklayarak, uygulama sayfasına yöneliyoruz.
Bu sayfada uygulamamız olmadığı için , ”Add An Application” sekmesine tıklayarak uygulama ekleme sayfasına yöneliyoruz.
223 | S a y f a
Bu kısım da ikinci seçeneği seçerek uygulama galerisinde hazır olan uygulamalardan istediğimizi hesabımıza ekleyebiliyoruz.
224 | S a y f a
Hesabımıza yüklemek istediğimiz uygulamayı bulduktan sonra sağ altta bulunan onaylama butonuna tıkladıktan sonra, uygulama hesabımızla etkileşime geçecektir.
Bu bölümde ise, hesabımızın kullanıcı adını ve şifresini, girmemiz gereken gerekli alanın açılması için ikinci bölümü seçiyoruz.
225 | S a y f a
Karşımıza çıkan açılır pencerede uygulamamıza giriş yaptığımız kullanıcı adı ve şifresini giriyoruz.
Bu ve sonradan ekleyeceğiniz uygulamalar için artık her seferinde kullanıcı adı ve şifre girmenize gerek kalmadan tüm uygulamalarınıza tek bir adresten ulaşabileceksiniz.
226 | S a y f a
Uygulamalarınızı ekledikten sonra; https://account.activedirectory.windowsazure.com/applications/default.asp x Adresinden artık bütün hesaplarınızı kontrol edebilirsiniz ve kullanıcı bilgilerinizi düzenleyebilirsiniz.
227 | S a y f a
Birden fazla kullanıcı ekleyerek, eklenmiş olan uygulamalara atama yaparak diğer kullanıcıların da hesaplarını yönetmelerini sağlayabilirsiniz.
8.15. Veri Tabanı
Uygulamalarımız için gerekli olan veri tabanı işlemlerini de Azure üzerinden kolayca halledebiliriz.
Sol menüden Sql Database bölümünü seçerek Create A Sql Database sekmesini tıklayarak veri tabanımızı oluşturmaya başlayalım.
228 | S a y f a
Bu bölümde ihtiyaçlarımız doğrultusunda yapılandırma ayarlarını yapıyoruz. Kullanıcı adı oluşturduktan sonra hangi alan için kullanacaksak ona göre seçim yapıyoruz. Bu örnekte web üzerinden çalışacak bir uygulama için veri tabanı oluşturduk. Eğer daha önce bir veri tabanı oluşturmamışsanız Azure üzerinde, New SQL Database Server seçeneğini seçiniz.
Bu bölümde bağlantı ayarlarımızı yapıyoruz. kurabilmemiz için gerekli parametreleri belirliyoruz.
229 | S a y f a
Veri
tabanına
bağlantı
Artık veri tabanımız oluştu, veri tabanına erişebilmemiz için bir önceki tabloda girdiğimiz kullanıcı adı şifresi ile giriş yapıyoruz.
230 | S a y f a
Veri tabanı yönetim sayfasına girdikten sonra, sol alt köşede bulunan Desing bölümünden yeni bir database oluşturuyoruz ve tablo ekleyerek kolonları belirliyoruz. Eklediğimiz kolonları silme işlemi ise My Work sekmesi altında yer almaktadır. Gerekli düzenlemeleri yaptıktan sonra Save diyerek veri tabanı işlemlerimizi sonlandırıyoruz.
Dışarıdan veri tabanımıza bağlantı kurabilmemiz için, veri tabanı ismine çift tıklayarak kontrol sayfasına yöneliyoruz. En alt seçenekteki bölümden; “View SQL Database connection string for ADO.NET ODBC, PHP and JDBC” seçeneğini seçerek bağlantı sorgumuzu elde ediyoruz.
231 | S a y f a
Bu bölümde hangi bağlantı mimarisini kullanacaksak onu seçip uygulamamızın veri tabanımızla bağlantı kurmasını sağlıyoruz. Not: IP adresinizi izin listesine eklemeniz gerekmektedir Bunun için yapmanız gereken; Configure sekmesine gelip “ADD TO ALLOWED IP ADDRESESS” sekmesine tıklamanız yeterli olacaktır.
232 | S a y f a
233 | S a y f a
234 | S a y f a
HTML HTML ( Hyper Text Markup Language - Zengin Metin İşaretleme Dili ) günümüzde uygulama tasarımı için kullanılan metin tabanlı dildir. Html, bir programlama dili olmadığı için Html kodlarıyla kendi başına çalışan bir yapı kurulamaz. Ancak bu dili yorumlayabilen programlama dilleriyle birlikte kullanılarak uygulama yazılabilir. HTML,W3C tarafından standartlaştırılmaktadır. HTML, “etiket” ismi verilen çeşitli başlıklardan oluşmaktadır. Web kavramı, CERN’de bir bilgisayar programcısı olan Tim Berners-Lee’nin HTML adlı bilgisayar metin dilini bulup geliştirmesiyle başlamıştır. 1980 yılında CERN’de görevli olan Tim Berners-Lee, CERN araştırmacılarının bilgilerini ve dokümanlarını birbirleriyle paylaşabilmeleri için geliştirdiği bir dildir. Bu yüzden ilk örnek olarak ENQUIRE isimli sistemi önerdi. 1980 yılına gelindiğinde internet tabanlı sistemin ilk temellerini yine aynı isim attı. 1990 yılında HTML işaretleme dilini geliştirmesinden sonra World Wide Web (WWW) sistemini kurmuştur. Bu şekilde CERN’de bilgi paylaşımını kolaylaştırma amacı doğrultusunda ortaya çıkan HTML günümüzde hayatımızın vazgeçilmezi olan internetin başlıca temelini oluşturmuştur.
9.1. HTML GELİŞİMİ
1995 – HTML 2.0
1997 – HTML 3.2
1998 – Web Standartları Projesi
1999 – HTML 4.0
2000 – XHTML 1.0
2004 – XHTML 2.0
2004 – HTML5
235 | S a y f a
9.2. HTML5 TEMEL YAPISI Temel HTML5 yapısını aşağıdaki tabloda görmekteyiz.
<meta charset="utf-8" /> Bilge Adam
__________________________________________________________ Html sayfası her zaman içim DOCTYPE etiketi ile başlar ve ardından , , etiketleri tanımlanır.
9.3. TEMEL ETİKETLER DOCTYPE, hazırladığımız sayfaların hangi tipte bir belge olduğunu tarayıcıya bildirmek için kullanırız. Bu sayede tarayıcı bu sayfayı hangi standartlara (hangi HTML sürümüne) göre yorumlayacağını anlamış olur. Eğer DOCTYPE kullanılmazsa tarayıcılar sayfaları standart’ a uygun yorumlamayacak, dolayısıyla her tarayıcı size farklı farklı sonuçlar verecektir.
Bu etiket kapsayıcı etiket olarak kullanılır. Diğer etiketler bu etiket içerisinde yer almaktadır. Tarayıcı ve arama motorları tarafından okunan bölüm olan bu etiket içerisinde diğer meta data etiketleri yer almaktadır. title, scripts, meta, css, link, gibi tag’ leri barındırmaktadır. <meta>
Meta etiketi sayfa hakkında tarayıcılara ya da arama motorlarına bir takım bilgiler sunar.
Charset özelliği sayfada kullanılan karakter kümesini tanımlamak için kullanılır. HTML5 ile yeni tanımlanan bir özelliktir. Sayfamız için charset tanımlaması yapmamız gerekmektedir. Eğer tanımlama yapmazsak, sayfadaki Türkçe ve özel karakterlerin gösteriminde problemler yaşayabilirsiniz. Charset tarayıcıların karakter ya da sembolleri düzgün bir şekilde göstermeleri için kullanılan bir yapıdır. 237 | S a y f a
Name: Meta etiketi içerisindeki değer atanacak olan önceden tanımlı alt özellik isimlerini tanımlamak için kullanılır. Bu özellik ile tanımlanan alt özelliğe değer atamak için CONTENT özelliği kullanılır.
Name özelliğine atanabilecek alt özellikler:
author: Güncel sayfanın yazarının veya iletişim bilgilerinin belirtilmesini sağlar.
distribution: Sayfanın (sitenin) hitap ettiği bölgenin belirtilmesini sağlar. Aşağıdaki değerleri alır.
Global: Tüm internet ağına hitap ettiğini belirtir. Local: Sitenin bulunduğu IP adres bloğunun ait olduğu ülkeye hitap ettiğini belirtir. IU (international Use): Kamuya hitap etmediğini belirtir.
expires: Sayfanın son geçerli olduğu tarihi GMT formatında belirtir. Sayfayı daimi olarak geçersiz kılmak için content özelliğine '0' değeri atanmalıdır.
<meta name="expires" content="Thu, 31 dec 2015 23:59:59 gtm" />
robots: Arama motorlarına sayfa ve sayfadaki linklerin takibi hakkındaki davranışlarının bildirilmesini sağlar. content özelliği aşağıdaki değerleri alabilir. Virgül ile ayrılarak birkaç değer birden belirtilebilir.
index: Sayfanın dizine eklenmesini bildirir. follow: Sayfa içindeki bağlantıların/linklerin izlenmesini bildirir. archive: Sayfanın ön izleme için ekran görüntüsünün oluşturulmasını bildirir. noindex: Sayfanın dizine eklenmesini engeller. nofollow: Sayfa içindeki bağlantıların/linklerin izlenmesini engeller. noarchive: Sayfanın ön izleme için ekran görüntüsünün oluşturulmasını engeller. Daha önce oluşturulduysa silinmesini sağlar. (Ön izlemenin silinmesi arama motorlarına göre farklılık gösterebilir.) all: Tüm olumlu bildirimleri uygular. Arama motorları index, follow ve archive bildirimlerinden farklı bildirimleri de kabul ediyor olabilir. Bu yüzden arama motorunun yardım/destek sayfasına bakınız. none: Sayfanın göz ardı edilmesini bildirir. noodp: Eğer sayfa DMOZ dizininde kayıtlı ise arama sonuçlarında DMOZ dizinindeki açıklamanın yerine sayfanın kendi açıklamasının kullanılmasını sağlar. Bu değer, özellikle MSNBOT (live.com) için geçerlidir.
Bir arama motoru robotu aksi belirtilmediği sürece bir sayfayı dizine ekleyebilir, sayfadaki linkleri takip edebilir ve sayfanın ön izlemesini oluşturabilir. Bu yüzden robots özelliği ile all, index, follow ve archive değerlerinin kullanımının çok özel bir anlamı yoktur. Bunlar yerine sadece robotu engellemek amacıyla, engelleme amacına göre none, noindex, nofollow ve noarchive değerlerinin kullanımı daha doğru olacaktır. Alttaki örnek: index, follow ve archive değerlerinin uygulanmasını gösterir. <meta name="robots" content="all" />
Alttaki örnek: Arama motoruna sayfayı dizine eklememesini fakat sayfadaki linkleri takip etmesinin bildirilmesini göstermektedir. <meta name="robots" content="noindex, follow" />
Alttaki örnek: Arama motoruna sayfayı dizine eklemesini fakat sayfadaki linkleri takip etmemesini ve sayfanın ön izlemesinin oluşturulmamasının bildirilmesini göstermektedir. <meta name="robots" content="index, nofollow, noarchive" />
Tarayıcı görüntülendiği anda pencere başlığında ve sekme başlığında gösterilecek olan metinin tanımlandığı etikettir. Örnek:
242 | S a y f a
Bilge Adam Yazılım ___________________________________________________________________
<script> Sayfamıza javascript kod bloklarını eklememiz için kullanılan etikettir. Head etiketi içerisinde kullanıldığı gibi body etiketi içerisinde de kullanılabilir.
Özelikler:
src: {url} harici bir script dosyasını belgeye dâhil etmek için kullanılır. Bu özellik kullanılırsa <script> blokları arasına kod yazılamaz.
async: Harici bir JavaScript dosyasındaki kodların eş zamansız çalışmasını sağlayan özelliktir.
defer: Bu özellik sadece src özelliği ile harici bir JavaScript dosyası eklendiyse çalışır. Sonradan dâhil edilen JavaScript kodlarının sayfa yüklendikten sonra çalışmasını sağlar.
type:
Örnek:
<script> var d = new Date(); var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; document.getElementById("demo").innerHTML = days[d.getDay()];
___________________________________________________________________ Sayfanın gövdesini oluşturan etikettir. İki gövde arasında yazdığımız tüm kodlar kullanıcıya gösterilecektir. Kullanım:
Kullanıcıya gösterilecek olan sayfa içeriği bu alanda tanımlanacak
___________________________________________________________________ HTML elemanına benzersiz bir isim vermek için kullanılır. Kullanım:
___________________________________________________________________ CSS kodlarının atanması için kullanılan etikettir. Bir elemana birden fazla class tanımlayabilirsiniz. Kullanım:
Yapısal etiketler tasarlayacağımız web sitesinin yapılarını belirleyen temel etiketlerdir. HTML5 ile gelen bu etiketler sitemizin daha düzenli bir yapıya sahip olmasını sağlar. Google gibi arama motorları web sitesinde başlıklara göre index’leme yaptığından dolayı bu etiketler içerisinde yer alan içerikler başlıklara göre gruplanıp kullanıcının arama sonuçlarına yansıtılmaktadır. Arama motorları tarafından tercih edilen bir sayfanız olsun istiyorsanız, uygun başlıklar içinde gerekli kodlamaları yapmalısınız.
245 | S a y f a
Sayfanın başlık kısmının tanımlandığı ve içerisinde bulunması gereken yapıların gruplandığı etikettir. İçerisinde H1, H2, H3, H4, H5, H6 gibi başlık etiketlerinin yanı sıra logo banner gibi yapılarda bulunabilir. Bir sayfada birden fazla etiketi kullanılabilir. Header etiketi section, aside ve article etiketleri içerisinde de kullanılabilir. Örnek: