msHOWTO

16 Mayıs 2012 Çarşamba

Entity Framework Giriş ORM Nedir ?

Merhaba arkadaşlar.Bu makaleyi şuan okuduğunuza göre daha önce ado.net ile uygulama geliştirmiş veya en kötü ihtimalle ado.net in ne olduğunu nasıl çalıştığını bir veri tabanına nasıl bağlantı yapıldığını ve uygulama içerisinden nasıl veri tabanı işlemleri yapıldığını biliyor olduğunuzu düşünüyorum arkadaşlar.Şimdi şu ana kadar ki uygulamalarımızda veri tabanı işlemlerini nasıl yapıyorduk ? Öncelikle veri tabanımızı oluşturup daha sonra uygulama tarafına geçip ilgili yerlere veri tabanı işlemleri yapan kodlarımızı yapıyorduk değil mi ? Yani şekil olarak resmetmek gerekirse ;

Yukarıdaki şekle bakıldığında hangi platformda olursa olsun uygulamamız direk olarak bir veri tabanına bağlı durumda.Bu durumda uygulama üzerinden veri tabanını etkileyecek herhangi bir işlem yapmak istediğimizde sql ifadeleri kullanmak durumundayız.Peki bu sistemin nasıl dezavantajları var da bugün sizlere anlatacağım ORM araçları ortaya çıkmıştır ?


  • Öncelikli olarak eğer bir veri tabanı uygulaması yazacaksanız kesinlikle sql bilmek zorundasınız.Aksi takdirde hiç bir şekilde veri tabanı işlemlerini uygulamanıza yaptıramazsınız. 


  • İkinci olarak ise bu sistemde öncelikle database oluşturulup daha sonra uygulama üzerinden sql ifadeleri ile veri tabanı işlemleri yapılmaktadır.Bu durum da hem ekstra zaman kaybı ve ekstra iş kaybı yaşatmaktadır.Malumunuz üzere işverenin tek düşündüğü durum para olduğu için bizim gibi oldukça değerli olan yazılımcıların minimum zamanda maksimum iş çıkarmaları işveren için oldukça önemlidir.
  • Üçüncü bir dezavantajı ise tamamen database bağımlıdır.Yani çalıştığınız yer bir anda artık bundan sonra oracle yerine mssql kullanacağız dediğinde oturulup oldukça fazla düzenlemeler yapılmak zorundadır.Hele birde düşünün ki web uygulaması yapıyorsunuz.Bu database değişikliliğine uyumun çok kısa bir süre içerisinde olması gerekmektedir değil mi ? 
  • Bir diğer dezavantajı ise yazılımcının database işlemleri arasında boğulup kaldığı için uygulamanın mantıksal kısımlarına gerektiği kadar zaman ayıramama durumu yaşamaktadır.
  • Son olarak da uygulamanız üzerinden database deki herhangi bir nesnenin tablo , view , sp hatta kolona kadar yapısal özelliklerini değiştirmek için uzun uzadıya sql ifadeleri yazmak zorundasınız.
Evet arkadaşlar şuana kadar kullandığınız yöntem ne kadar zormuş değil mi ? Şimdi sizlere öyle bir konu anlatacağım ki siz de ben neler çekiyormuşum diyeceksiniz :) Evet tahmin ettiğiniz gibi ORM ' e giriş yapacağız.

Şimdi arkadaşlar ORM nedir ? öncelikle bu sorunun cevabıyla başlayalım.Orm yani Object Relational Mapping , veri tabanınızdaki tabloları class lara , kolonları property lere , tabloların içindeki kayıtları da object lere dönüştüren ve tüm bu dönüşün sonucunda oluşan class lar ve objeler üzerinden veri tabanı işlemlerinizi yapmayı sağlayan bir teknolojidir.Yani kısaca tanımlamak gerekirse database modelini uygulama modelindeki nesnelere uyarlar.Aslında yaptığı iş tam olarak database modelini uygulamadan soyutlayarak nesneler üzerinden işlem yapmamızı sağlar.

Orm in ne olduğunu anladıktan sonra bir de şekle dökmek gerekirse ;




Yukarıdaki şekle bakıldığında uygulama orm e bağlı olduğunu görebiliriz.Database le direk olarak herhangi bir bağlantısı söz konusu değildir.Peki burada bizim yapmak istediğimiz databse işlemlerimiz nasıl oluyor da sql ifadesi yazmadan gerçekleşiyor? . Uygulama tarafında oluşan nesneler üzerinden biz database işlemi yaptığımızda orm tarafından bu işlem sql ifadesine dönüştürülüyor.Bu işleme Code Generating işlemi denir.Tüm orm araçları aynı işlemi yaparlar.Mesela siz uygulamanızda bir nesne üzerinden bir tabloya kayıt ekleme işlemi yapmak istediğinizde orm otomatik olarak insert sql ifadesini oluşturup database e gönderir.Bu sayede sizin sql bilmenize gerek kalmamaktadır.

Orm in ne olduğunu ve nasıl çalıştığını anladıktan sonra maddeler halinde avantajlarına ve dezavantajlarına bakalım arkadaşlar.

Avantajları ;

  • OOP olarak kod geliştirmeye imkan sağlamaktadır.
  • Sql bilmeden bir veri tabanına bağlanabilir ve sql ile ilgili bir çok işlemi rahatlıkla yapabilmek.
  • Herhangi bir database bağımlılığı yoktur.
  • Oldukça esnek bir yapı sağlamaktadır.Yani oracle kullanıyorken bir anda mssql i kullanabiliriz.
Dezavantajları :
  • Performans.Bir ado.net kadar hızlı çalışmamaktadır.
  • Database den bilgi alış-verişi sırasında kontrol %100 bizde değildir.Bazen oluşturulan sql ifadelerinde sorun çıkabilir veya biz daha güzel ve hızlı çalışacak sql ifadeleri yazabileceğimiz durumlar olabilir.Fakat tüm sql ifadelerini code generating ile kendi oluşturduğu için bu bir dezavantajdır.
  • Veri tabanı bağımsızdır.Fakat uygulama tarafındaki nesneler ile veri tabanındaki nesneler birbirine map edildiği için nesne bağımlılığı vardır.
Farklı platformlarda farklı farklı orm araçları mevcuttur arkadaşlar.Mesela java da Hibernate , microsoft ta , EntityFramework ... Aynı zamanda hibernate altyapısını kullanan ve .Net platformu için NHibernate orm aracı vardır.Daha bir çok araç mevcuttur.Fakat temelinde hepsi orm mantığı ile çalışırlar.

Elimden geldiğince ORM i anlatmaya çalıştım arkadaşlar.Sonraki makalelerimde Microsoft'un ORM araçlarından olan Entity Framework ü anlatacağım.Tekrar görüşmek dileğiyle ...

9 Mayıs 2012 Çarşamba

Sql Server Transaction Isolation Levels

Merhaba arkadaşlar. Bu makalemde sizlere transaction ile ilgili oldukça önemli konu olan Isolation Levels 'ı anlatacağım.Daha önceki makalelerimde transaction ı nasıl kullanacağımızı neden kullanacağımızı detaylı olarak anlatmıştım.Bu makalemde anlatacağım konu transaction ları izolasyon etme seviyelerinden bahsedeceğim.Yani diğer bir deyişle aynı anda aynı veriler üzerinde çalışan transaction ların nasıl çalışacaklarını veya nasıl sonuçlar alacaklarını belirleyebildiğimiz seviyelerden bahsedeceğim.

Öncelikle native yani tüm veri tabanı sistemlerinin kabul ettiği 4 adet isolation level lar vardır.Fakat MSSQL Server ise bize bunlara ek olarak 2 adet isolation level sağlamaktadır.

1-)Read Uncommited(level 0)
2-)Read Commited(level 1)
3-)Repeatable Read(level 2)
4-)Serializable(level 3)

Bunlara ek olarak Mssql in bizlere sağladıkları ise ;

1-)Read Commited Snapshot Isolation
2-)Snapshot Transaction Isolation

Yukarıdaki isolation level ları incelemeden önce ortak zamanlı erişim sorunlarını anlatmak istiyorum arkadaşlar.Nedir ortak zamanlı erişim sorunları?Aynı anda birden fazla transaction ın veya session ın aynı veri üzerine erişmek istemesi ve işlem yapmak istemesi sırasında ortaya çıkabilecek olan sorunlardır.4 adet sorun karşımıza çıkmaktadır.

1-) Lost Updates:Aynı anda birden fazla transaction aynı anda bir veri üzerinde güncelleme yapmak istediği zaman en son işlem yapan transaction ın kaydı geçerli olur.Bu yüzden veri kaybı yaşanır.

2-)Dirty Reads:Bir transaction ın bir veri üzerinde yapmış fakat commit etmemiş olduğu bilgileri diğer transaction tarafından gerçek kayıtmış gibi okuması durumudur.

3-)Non-Repeatable Reads:Bir transaction bir veriyi okusun ve kendi içinde işleme soksun.Bu transaction commit etmeden başka bir transaction bu veriyi okusun.Daha sonra işlem yapan transaction tekrar veriyi okumak istediğinde veri aynı veri olmayacağı için sorun yaşanmaktadır.

4-)Phantom Reads:Aynı anda çalışan transaction düşünelim.Bir transaction bir tablodaki verilerin tamamını çeksin ve kendi içindeki işleme soksun.Bu sırada da diğer transaction aynı tabloya veri ekleme işlemi yapsın.Daha sonra ilk transaction tekrar verileri çekmek istediğinde yeni eklenen veriler hayalet veri olarak görünür.

İşte tüm bu sorunlara çözüm olarak isolation level lar vardır.Hadi gelin şimdi onları inceleyelim arkadaşlar.

Read Uncommited

      Bir veri üzerinde bir kullanıcı transaction yaparken diğer kullanıcılarında değişikliğe uğramış fakat commit edilmemiş verileri görebilmesini sağlayan level'dır.Bu durum bize performans sağlar fakat verimizin güvenliğini elimizden alır neredeyse.Çünkü ya yapılan transaction commit edilmezse yani bir hata oluşur ve tüm yaptığı işlemleri rollback yaparsa ne olacak ? İşte bu durumda ortaya çıkan soruna Dirty Read denilir.Yani kısacası bir transaction işlemi yapılırken commit edilmese dahi diğer kullanıcılar transaction ın yaptığı işlemlerin sonucunu transaction sırasında görebilirler.Dirty reads,lost updates,non-repeatables reads ve phantom reads sorunları vardır.

Peki bu level ı nasıl kullanacağım ? 

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED


Yukarıdaki gibi sql komutu ile oldukça basit bir şekilde aktif hale getirebiliriz.

Read Commited

     Bu level da ise eğer bir veri üzerinde transaction uygulanıyorsa diğer transactionların bu veriye erişmesini engeller.Sql server'ın default level ı budur arkadaşlar.Daha önce denediniz mi bilmiyorum fakat eğer bir veri üzerinde bir tansaction işlemi yapılıyor ise sql server da o veriye erişim engellenir.Peki bu sırada diğer sorgular veya transactionlar ne olacak ? Veri üzerindeki transaction'ın sonlanmasını beklemekten başka hiç bir şansları yok :)Read Uncommited ın ortaya çıkardığı dirty read sorununu ortadan kaldırır.Fakat losts updates sorunu vardır.

Peki bu level ı nasıl kullanacağım ? 

SET TRANSACTION ISOLATION LEVEL READ COMMITTED

Yukarıdaki gibi sql komutu ile oldukça basit bir şekilde aktif hale getirebiliriz.

Repeatable Read

     Diyelim ki bir transaction işlemleri arasında bir veriyi çekti ve işlem yapmaya başladı.İşlemini tamamlamadan yani commit edilmeden bir başka transaction veya kullanıcı o verideki değeri değiştirdi.Transaction işlemlerini yaparken tekrardan o veriyi okuyup değerini almak istedi.Eee veri eski veri değil. Doğal olarak transaction'ın işlemlerinin sonucu yanlış çıkacaktır.İşte bu sorunu ortadan kaldırmak için bu level kullanılmaktadır.Yani kısaca bir transaction tarafından kullanılan veri diğer transaction tarafından okunamaz.Fakat buradaki asıl amaç bir transaction tarafından okunan ve kullanılan verinin değiştirilmemesidir.Bu sayede dirty reads,lost updates,non-repeatables reads sorunları ortadan kalkar.Fakat phantom reads sorunu vardır.

Peki bu level ı nasıl kullanacağım ? 

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ


Yukarıdaki gibi sql komutu ile oldukça basit bir şekilde aktif hale getirebiliriz.

Serializable

    Veri ekleme,silme ve güncelleme yapan transaction boyunca veri erişime kapanır.Bu sayede hiç bir ortak zamanlı sorun ortada kalmaz.Fakat işlemler çok fazla birikir.Bu da bize performans sorunu yaşatır.

Peki bu level ı nasıl kullanacağım ? 

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

Yukarıdaki gibi sql komutu ile oldukça basit bir şekilde aktif hale getirebiliriz.

Read Commited Snapshot Isolation

      Bu level da Read Commited level da oluşan Shared Lock durumu ortadan kalkar.Yani bir transaction bir veride güncelleme yaparken bir başka transaction bu veriyi okuyabilir.Bir transaction içerisinde kalmış ve commit edilmemiş verilerin tempdb veritabanına snapshot larını kaydeder.Böylece diğer transactionların verileri okuması sağlanmaktadır.
Kullanılabilmesi için database seviyesinde READ_COMMITTED_SNAPSHOT parametresinin "on" konumunda olması gerekmektedir.Default olarak "off" ayarlanıktır.

ALTER DATABASE Northwind SET READ_COMMITTED_SNAPSHOT ON

Olarak kullanılır.

Snapshot Transaction Isolation

    Bir üstteki level dan tek farkı burada yapılan konfigurasyonun transaction bazında olmasıdır.
Kullanımında öncelikle database seviyesinde ayar yapılması gerekir.

ALTER DATABASE Northwind SET ALLOW_SNAPSHOT_ISOLATION ON

Daha sonra ise transaction seviyesinde ayarlama yapılması gerekmektedir.

SET TRANSACTION ISOLATION LEVEL SNAPSHOT


Evet arkadaşlar umarım faydalı olmuştur.Bir sonraki makalemde görüşmek dileğiyle...

3 Mayıs 2012 Perşembe

Sql Server Index Yapısı

Merhaba arkadaşlar.Bu makalemde sizlere index nedir? Nasıl bir yapısı vardır ? Ne gibi yararlar sağlar ? Nasıl kullanılır ? Neden kullanılır ? gibi detaylı olarak index yapısını anlatacağım.Eğer bu makaleyi okuyorsanız ya küçük veya orta çaplı database ler ile çalıştınız yada verilerinin oldukça birikti sorgularınız geç cevap veriyordur.Açıkça söylemek gerekirse ben index lerin ne olduğunu büyük database lerle çalışmadan bilmiyordum.Ta ki bir gün bir projede database deki birden fazla tablonun içerisindeki kayıtların yüzbinleri hatta milyonları bulabileceği söylenene kadar.İlk yaptığım hemen 3 kolonlu basit olarak adı ve soyadı bilgilerini tutan bir tablo oluşturmak oldu.Daha sonra basit bir while döngüsü ile 1.000.000 kayıt girdisi yaptım.Sonrasında ise sadece select * from adi where adi='koray99999' şeklinde bir sorgu çekmek oldu.Bakın ne join yapısı var ne sub query filan var.Basit bir sorgu.Dedim en fazla 2-3 saniyede getirir sonucu dedim.Fakat hiç de öyle olmadı :).Oldukça fazla beklemiştim.Dedim bu böyle olmaz.Mutlaka bir yolu yöntemi vardır.Araştırmalarım sonucunda index nimetini buldum.Index yapısını oluşturduktan sonraki sorgumun sonucu bana 1-2 saniye gibi müthiş bir hız farkıyla döndü.Bu bizzat benim yaşadığım örnekti.Bir de düşünün arkadaşlar turkcell avea gibi telefon şirketlerinin database lerini ve bu databaselere gelen sorguları ? Yani kısacası eğer veriniz oldukça fazla ise yada en azından bunu öngörebiliyorsanız yüksek performans almak zorundasınız.Bunun için de index yapısı oluşturmalısınız arkadaşlar.Index'in faydasını anlattıktan sonra hadi gelin Index in yapısını inceleyelim.

Sql server'da 2 farklı index yapısı mevcuttur.Clustered ve Non-Clustered Index.

1-)Clestered Index:Kümelenmiş index olarak türkçeye çevirilebilinir.Diyelim ki arkadaşlar özel bir dershane açtık.İlk gün 10 tane öğrenci geldi kayıt ettik.Bu öğrencilerin dosyalarını çekmeceye koyduk.2.gün 15 öğrenci kaydoldu ve bu öğrencilerin dosyalarını da çekmeceye koyduk.İlk hafta sonunda toplam 60 öğrencimiz oldu.Çekmecemiz doldu bu sefer de dolablara koymaya başladık.Bu şekilde durumu kurtardığımızı düşündük.Fakat yıllar geçti bu sefer dolaplarda yetmedi hatta arşivlemeye başladık.Yer sıkıntımız oluştu.Hatta bir gün Koray Düzgün adında bir öğrencimizin bilgisine ulaşmak istedik.O kadar veri yığınının içinde ara ki bulasın.Bundan bir ders çıkardık ve alfabetik sıraya göre sıralayıp tüm dosyaları kümeleştirdik.Bir sonraki öğrenci geldiğinde direk hangi kümedeyse hangi sıradaysa gidip bulduk.Ne kadar hızlı sonuca ulaşıp ne kadar iş ve zaman kazancı sağladık.İşte arkadaşlar database imizdeki verilere clustered index yapısı oluşturursak aynı şekilde kazanç sağlarız.Clustered index yapısında elimizdeki veriler sıralı olarak belli bir grup içinde bulunur.Bu şekilde çok daha hızlı bir şekilde sonuca ulaşırız.Aslında eğer veri tabanı oluşturduysanız daha önce farkında olmadan kesinlikle eminim ki clustered index kullandınız.Hepiniz bir tabloda bir kolona mutlaka primary key koymuşsunuzdur.Hatta identity bile verdiniz.Identity verdiğiniz anda o kolondaki veriler sıralı olarak kaydedilmiyor mu ? Alın size işte clustered index.Clustered index 3 yapıdan oluşur.


Clustered index yapıldığında sıralanan veriler leaf de tutulur.Yukarıdaki örnekte öğrencinin dosyasına ulaştığınızda direk verinin kendisine ulaşıyoruz değil mi ? Bunun nedeni de clustered index de veriler leaf aşamasında bulunur.Baş harflerine göre gruplama yaptığımızda ise bu grup bilgileri de intermadiate level larda tutulur.Bilinmesi gereken en önemli noktalardan birisi bir tabloda sadece 1 tane clustered index oluşturulabilinir.

2-)Non-Clustered Index:Bir kitap aldınız elinize.Oldukça kalın bir kitap.Diyelim ki sql server ile ilgili bir kitap olsun.Ve index konusunun geçtiği sayfaları tek tek bulmak istiyorsunuz.Ne yaparsınız?Bütün kitabı arayıp bulur musunuz? Yok artık . Bazı kitaplarda sonlarında içinde geçen konular ve bu konuların ve ya kelimelerin sayfa numaraları liste halinde yazılıdır.Ne yaparsınız böyle bir durumda?Öncelikle gidip arkadan hangi sayfalarda olduğunu bulursunuz.Daha sonra o sayfalara bakıp veriye ulaşırsınız.İşte en güzel non-clustered yapısı.Bu örnekten de anlaşıldığı gibi non-clustered yapıda verinin kendisine ulaşamazsınız.Bu yapıda leaf level larda verinin bulunduğu adres bulunur.Daha sonra tekrardan root a çıkılıp aşağıya doğru inilerek verinin kendisine ulaşılır.Sql server 2005 de 255 tane bir tabloya non-clustered index oluşturabiliyorduk.Sql server 2008 ile birlikte 999 adet oluşturulabiliniyor.Fakat pek tabi bir tabloya bu kadar non-clustered index verilmez.Ben bolca var nasılsa her kolona koyayım oh ne güzel gibi bir düşünce olmasın.Çünkü bu sefer index yapısı arka planda karışıyor.Dikkat edilmesi gereken şu ki en fazla sorgu çekilen kolonlara verilmek en doğrusudur.

Clustered yapılarını kavradıktan sonra bakalım tüm bu anlatılanlar ne kadar doğru ? Hemen test yapalım arkadaşlar.


DECLARE @i INT
SET @i=0
WHILE(@i<100000)
BEGIN
INSERT INTO dbo.Telefonlar
SELECT Ad='Koray'+CAST(@i AS nvarchar(30)),SoyAd='Düzgün'+CAST(@i AS NVARCHAR(30)),TelefonNo='123456789'
SET @i=@i+1
END

T-Sql kodları ile verilerimizi kaydettik.Daha sonrasında ise ,

--Aşağıdaki işlemle Kaç logical read yaptıgımı gösteren sistemi açtým
SET STATISTICS IO ON

-- Aşağıdaki  işlemle Kaç Kaç milisaniye geçtiğini gösteren sistemi açtým
SET STATISTICS TIME ON

Daha sonra ise 

SELECT * FROM dbo.Telefonlar WHERE Ad='Koray99993'

Olarak select çekin.Ve çıkan verilere göz atın.Daha sonra ise 

--Clustered indeks tanımladım

CREATE CLUSTERED INDEX TelefonIndeks ON dbo.Telefonlar(AdresID)
SELECT * FROM dbo.Telefonlar WHERE AdresID=80000



Olarak select çekin.Ve çıkan verilere göz atın.Daha sonra ise 

REATE NONCLUSTERED INDEX AdaGoreIndeksle ON dbo.Telefonlar(Ad)

--Non-Clustered indeks tanımladım

SELECT * FROM dbo.Telefonlar WHERE Ad='Koray99993'

Olarak select çekin.Ve çıkan verilere göz atın.Sonuçlardan farkı göreceksiniz.

Umarım faydalı olmuştur arkadaşlar.Bir sonraki makalemde görüşmek dileğiyle...



30 Nisan 2012 Pazartesi

T-Sql Transaction

Merhaba arkadaşlar.Bu makalemde sizlere oldukça önemli ve kullanılan bir yöntemi anlatacağım.Transaction.Nedir bu transaction? Bir bütün olarak çalışması gereken bir takım sql komutlarınız olduğunu düşünün.Dolayısıyla bu komutlardan birisinin çalışması sırasında oluşacak bir hata sonucunda diğer sql komutlarının sonuçları da etkilenecektir.Bu konuya en güzel örnek banka havale işlemidir aslında.Düşünün ki siz bana 1000Tl havale yaptınız.Fakat banka sizden parayı çektikten sonra bir hata oluştu ve bana çektiği parayı yatırmadı.Eee ne olacak?Para nerede ? Para uçtu değil mi ? Sizden 1000tl gitti.Bana para gelmedi.Düşünün bu şekilde 100 kere hata oluştuğunu hatta çok daha fazla miktar havale sırasında hata oluştu.Banka batar :) İşte bu şekilde son derece önemli ve bir bütün halinde başarılı çalıştıktan sonra sonuçların yansıması gereken işlemlerde Transaction kullanılır.

Şimdi id,adi ve bakiyesi kolonlarından oluşan basit bir hesap tablomuz olsun.Bu tablo üzerinden havale işlemini yapan sql komutlarını yazalım .

update Hesap set Bakiyesi-=1000 where id =2

update Hesap set Bakiyesi+=1000 where id =3

Yukarıdaki sql komutları birlikte çalışması yani bütün halinde çalışması gerekmektedir.Diyelim ki bir hata oluştu.Çok basit bir hata fırlatalım hemen .

update Hesap set Bakiyesi-=1000 where id =2
update Hesap set Bakiyesi+=(select 10/0where id =3

Yukarıdaki division by zero hatası fırlattım basit olarak.Diyelim ki bir hata oluştu id si 2 olan hesaptaki müşteriden 1000 tl düşüyor.Fakat 3 'e aktarılmıyor.Bunu engellemek için akla gelen try catch dir.

begin try
update Hesap set Bakiyesi-= 1000 where id =2
update Hesap set Bakiyesi+=(select 10/0)  where id =3
end try
begin catch
print 'hata oluştu'
end catch

Fakat bu şekilde kullanırsak da ilk işlemi yapacak diğerinde hata oluşacağı için yapmayacaktır.Try catch de işimize yaramadı arkadaşlar. Tek bir çaremiz var transaction kullanmak.

begin try
      begin transaction
            update Hesap set Bakiyesi-=1 where id =2
            update Hesap set Bakiyesi+= (select 10/0)  where id =3
      commit tran--transaction da yazılabilir.Commiti gordugunde o ana kadarki işlemleri onaylar ve gerçek verilere yansıtır.    
end try
begin catch
      print ' hata oluştu '
      rollback tran --transaction da yazılabilir.
end   catch



Evet arkadaşlar yukarıdaki bir transaction yapısı oluşturursak eğer işlemlerimizin tamamı başarılı bir şekilde gerçekleşirse sonuçları kayıtlarımıza yansıyacaktır.Aksi taktirde hiç bir işlem olmayacaktır.Buradan anlaşılan şudur: Transanction da ya hep ya hiç mantığı vardır.

Umarım faydalı olmuştur arkadaşlar.Bir sonraki makalemde görüşmek dileğiyle...

T-Sql Trigger 2 - DDL Trigger

Merhaba arkadaşlar.Trigger konumuzun 2.partında Ddl Trigger ları anlatacağım.Önceki partta Dml trigger ları anlatmıştım.Ddl Trigger lar tanımlandığı sql server üzerinde çalıştırılan Ddl sorguları ile tetiklenen triggerlardır.Database oluşumundan tutun da view düzenlemesine kadar dml sorguların etki ettiği tüm database nesneleri üzerinden tetiklenebilirler.Farklı senaryolar ile ddl triggerların oluşturulmasını inceleyeceğiz arkadaşlar.

Not:Syntax i dml trigger lar ile aynıdır.Bu yüzden tekrardan incelemeye almayacağım.Dml trigger ları anlattığım makaleden syntax i hakkında bilgi edinebilirsiniz.

İlk senaryomuz server üzerinde herhangi bir tabloyu herhangi bir şekilde değiştirme işlemini engelleyen bir trigger oluşturmak olsun arkadaşlar.


create trigger TabloDuzenlemeEngeli
on database
for Alter_Table
as
      raiserror('Tablo düzenleme engeli',16,1)
      rollback

Yuarıdaki gibi bir trigger oluşturduğumuzda triggerımızın bulunduğu server üzerindeki tabloların yapısında değişiklik yapılmasını engellemiş oluruz arkadaşlar.Bu trigger da kullandığım 2 tane sql komutu vardır.Raiserror ile hata fırlatma işlemi yapabiliriz.İstediği parametreler sırası ile hata mesajı,severity değeri ve state değeridir.Rollback ise trigger tetiklenmeden önce yapılan işlemleri geri almak için kullanılır.Transaction konusunda detaylı olarak anlatacağım.Şuan üzerinde durmuyorum.

Diğer bir senaryomuz ise database oluşturma engeli vermek olsun.Bunun için de ,

create trigger VeriTabaniOlusturmaEngeli
on all server
for CREATE_DATABASE
as
      raiserror ('Adam ol la',16,1)
      rollback

Diğer bir senaryomuz ise database silme engeli vermek olsun.Bunun için de ,

create trigger VeriTabaniSilmeEngeli
on all server
for Drop_DATABASE
as
      raiserror ('Adam ol la',16,1)
      rollback

Gibi bir çok senaryo kurabiliriz arkadaşlar.Temel olarak anlaşılması gereken önemli nokta tüm database nesneleri üzerinde ddl sorguları çalıştırıldığında yani drop,create ve alter işlemi yapıldığında ddl triggerların tetiklenip içerisinde belirttiğimiz kodları işlemesidir.Diğer tüm özellikleri dml triggerlar ile aynıdır.

Umarım faydalı olmuştur arkadaşlar.Bir sonraki makalemde görüşmek dileğiyle ...


T-Sql Trigger 1 DML Trigger

Merhaba arkadaşlar.Bu makalemizde ki konumuz T-Sql üzerinden trigger oluşturmak.Öncelikle nedir trigger?Ne amaçla kullanılır? Bu soruların cevaplarını arayalım.Trigger'ı C# da ki event lara benzetebilirsiniz arkadaşlar.C# da nasıl ki bir button un click olayı buttona tıklandığı anda içindeki kodlar çalışıyorsa bizim oluşturduğumuz trigger database üzerinden hangi durumu kontrol ediyorsa o durum oluştuğunda kendi içerisindeki kodlar çalışmaktadır.Peki nerelerde kullanılır?En basit olarak bir tabloya çekilen sorguyu kontrol etmeden tutun da bir database oluşturulurken sizin istediğiniz kodların çalışmasına kadar bir çok amaçlar için kullanılır.Hadi gelin syntax ini inceleyelim.


go
create trigger TriggerAdi
on TriggerinEtkilencegiDatabaseNesnesininAdi
after insert
as
--Trigger tetiklendiği zaman çalışacak sql sorguları
 select * from shipers


2 farklı Trigger vardır.

1-) DML Trigger:Dml yani select, insert, update ve delete sorguları sonucunda tetiklenen trigger'lardır.

2-) DDL Trigger:Ddl yani drop,alter ve create sorguları sonucunda tetiklenen trigger'lardır.

     A-)After : Dml veya ddl sorguları çalıştıktan sonra tetiklenir.Dml veya ddl sorguları işlenir ve daha sonrasında trigger içerisine yazılan sorgular işlenir.

     B-)Instead of : Dml veya ddl sorguları çalıştıktan sonra tetiklenir.Dml veya ddl sorguları yerine trigger içerisine yazılan sorgular işlenir.

Basit örneklerden triggerlarımızı yazmaya başlayalım arkadaşlar.


create trigger tetikci
on shippers
after insert
as
 select * from shipers

Yukarıdaki tetikçi ismindeki triggerımız shippers tablosu üzerinde insert işlemi gerçekleştikten hemen sonra kendi içerisinde yazılan sorguları çalıştırmaktadır.Yani kısaca shippers tablosuna veri her eklendiğinde o tabodaki tüm kayıtları gösterir.

create trigger guncellemeTetikcisi on categories
 after update
 as
      print 'Güncelleme tamamlandı.'

Yukarıdaki trigger da categories tablosu üzerinde update işlemi her olduğunda geriye mesaj döndürür.

Basit olarak iki tane trigger oluşturduktan sonra bilinmesi gereken önemli bir noktayı anlatmam gerekmektedir.T-Sql de insterted ve deleted isminde özel tablolar bulunmaktadır.Siz bir insert işlemi yaptığınızda öncelikle verileriniz inserted tablosuna eklenir.Eğer işleminiz başarılı bir şekilde gerçekleşirse verileriniz kaydetmek istediğiniz tabloya kaydolur.Aynı şekilde deleted tablosunda da delete sorgusu çekildikten sonra veriler önce buraya atılır daha sonra silinir.Fakat dikkat ederseniz updated gibi bir özel tablo bulunmamaktadır.Çünkü update işleminde önce veri silnir daha sonra ekleme işlemi yapılır.Yani update işleminde hem deleted hem de inserted tabloları kullanılır.

Bu bilgiden sonra basit olarak inserted tablosunu kullanarak bir örnek yapalım...

go
create trigger Haberci on categories
after insert
as   
      select @sonId=CategoryId from inserted
      select * from categories where categorId=@sonId

Yukarıdaki örnekte categories tablosuna eklenen son kaydın tüm bilgilerini gösteren bir trigger yazdık.

Bir örnekte de deleted tablosunu kullanarak bir trigger oluşturalım arkadaşlar...

create trigger yedekci on shippers
after delete
as
      declare @firmaAdi nvarchar(50)
      declare @telefon nvarchar(24)
      select @firmaAdi = CompanyName , @telefon=Phone from deleted
      insert YedekDataBase.dbo.SilinenShippers values (@firmaAdi,@telefon)

Yukarıdaki örneğimizde shippers tablosunda bir kayıt silindiğinde YedekDataBase isimli database in  SilinenShippers isimli tablosuna silinen kaydı yedek olarak kaydeden bir trigger oluşturduk.Bu örneğimizde de görüldüğü gibi trigger ile silinen kayıtları otomatik olarak loglama yapabiliriz.

Şuana kadar tüm örneklerimizde bir işlem gerçekleştikten sonra Yani After ile kullanılan trigger lar oluşturduk.Fakat gerçekte bir veri tabanından veriler silinmez düşüncesinde olan yazılımcılardan olduğum için bir silme işlemi yapıldığında ne yapacağım ? Benim o silme işlemini engelleyip o kaydı pasif hale getirmem gerekmektedir(Pasif hale getirmek için önceden boolean tipinde bir kolon oluşturduğumu ve bu kolon uzerinden kontrol ettiğimi varsayalım) Şuana kadar trigger oluşturmak için kullandığımız yöntemlerle bu sorunu çözemem arkadaşlar.İşte burada devreye INSTEAD OF girmektedir.

İlk olarak senaryomuz diyelim ki istediğimiz bir tabloda istediğimiz bir kaydın silinmesini engellemek istiyoruz.Bu kayıt bizim için hayati önem arz ediyor diye düşünelim arkadaşlar.Bu işlemi aşağıdaki trigger ile kolaylıkla oluşturabiliriz.

create trigger silmeEngeli on categories
instead of delete
as
      declare @silinenId int
      select @silinenId=categoryId from deleted
      if @silinenId=8
      begin
            print 'Kayýt silinemez'
            rollback tran
      end
      else
      begin
            delete from Categories where CategoryID=@silinenId
      end

İkinci bir senaryoda silinmek istenen veriyi pasif hale getirmek istediğimizi düşünelim.Bu sorunu da aşağıdaki triggerla kolaylıkla çözebiliriz.

create trigger UrunSilmeEngelleyici
on Products
instead of delete
as
      declare @silinenId int
      select @silinenId=ProductId from deleted
      update Products set Discontinued=0 where ProductID=@silinenId




Peki oluşturduğumu tüm bu triggerlar nerede saklanıyor? Oluşturulan ddl trigger lar hangi tablo üzerinde oluşturulduysa yani hangi tabloda ddl işlemi yapıldığında tetikleniyorsa o tablonun altındaki trigger sekmesinde yer almaktadır.

Son olarak bir trigger ı istediğimiz anda enable edip istediğimiz anda disable etmek isteyebiliriz.Bunun için 2 yöntem vardır.İlk olarak ilgili trigger a sağ tıklayıp enable/disable seçeneğine tıklanarak yapılır.T-Sql ile de ,

disable trigger tetikci on shippers --triggerı disable eder
 go
 enable trigger tetikci on shippers --triggerı enable eder

Evet arkadaşlar bu makalemde triggerlara giriş yaptık.DML Triggerları anlattım.DDL Triggerları devamı olarak anlatacağım.Oldukça uzun oldu makale.Okurken sıkılıp yeter artık deme ihtimalinizi düşünerek diğer part ında anlatacağım.Görüşmek dileğiyle...



29 Nisan 2012 Pazar

T-SQL ile SQL Pagging

Merhaba arkadaşlar.Bu makalemde oldulça önemli ve çok yararlı işlem olam pagging yani sayfalamanın nasıl yapılacağını anlatacağım.Ama öncelikle sayfalamanın yararını iyice anlamamız gerekmektedir.Neden kullanılır? Diyelim ki milyonlarca kayıtın olduğu bir tablonuz var ve sorgu çekerek işlem yapacaksınız.Ve aradığınız verinin tahmini olarak nerelerde olduğunu biliyorsunuz.Neden tablodaki tüm kayıtlara sorgu çekeceksiniz ki o zaman.Gereksiz bekleme ve performans kaybı yaşarsınız.Fakat tablodaki tüm kayıtları istediğiniz sayıda sayfalama yaparsanız ve sorgunuzu bir kaç sayfaya atıp hemen sonuç elde etmek müthiş bir şey değil mi ? Bence evet.Hadi bu işlemin nasıl yapıldığına bakalım.

Öncelikle tüm kayıtları bir elde edelim .


SELECT * FROM dbo.Products

Daha sonra ise bu verileri bir şekilde ve benim istediğim türde sıralama yapmam gerekiyor.

SELECT * FROM dbo.Products ORDER BY ProductName

Bu işlemide yaptıktan sonra düşünmem gereken şu ki benim sayfalama yapmam için ve bir sayfada kaç kayıt gözükeceğini belirlemem lazım.Bunun için akla ilk gelen id kolonlarına bakmak olacaktır.Fakat unutulmaması gereken eğer silinen veri varsa düzgün sonuç alamayız.Id kolonundaki değerlerin üzerinden yola çıkamam.Onun için de kendi algoritmamı yazmam gerekmektedir.

DECLARE     @PageSize INT,
      @PageNumber INT,
      @FirstRow INT,
      @LastRow INT

SELECT      @PageSize = 10,
      @PageNumber = 2

SELECT      @FirstRow = ( @PageNumber - 1) * @PageSize + 1,
      @LastRow = (@PageNumber - 1) * @PageSize + @PageSize ;

Olarak algoritmamı yani bir sayfada kaç kayıt varsa ona göre verileri sayfalara ayırmak için gereken değerlerimi elde ettim.Şimdi yapmam gereken şudur.Eğer ben id kolonundan yola çıkamıyorsam kendim öyle bir kolon oluşturmam gerekir ki elde edilen satırlara otomatik sıra numarası atasın.Bu işlem için de Row_Number() over(Sıralı bir kolon) kodlarından yararlanmam gerekir.

select row_number() over (order by ProductID asc) as SatirNo, ProductID, ProductName   from Products

Olarak sıraları otomatik veren kolonumu da oluşturdum.Şimdi sıra geldi bu sorgudan tablo olarak dönen verilere where filtreleme kodu ile istediğim değerler arasındaki verileri çekmeye.

select * from (select row_number() over (order by ProductID asc) as SatirNo, ProductID, ProductName   from Products) Products where (SatirNo between  3 and 15)

Bu işlemi de yaptıktan sonra  3 ile 15 değeri yerine yukarıda bulduğum firstrow ve LastRow değişkenlerini verirsem işlemim tamamlanacaktır.

select * from (select row_number() over (order by ProductID asc) as SatirNo, ProductID, ProductName   from Products) Products where (SatirNo between  @FirstRow and @LastRow)

Parça parça anlattıktan sonra tam olarak sorgumuzu bir görelim .

DECLARE     @PageSize INT,
      @PageNumber INT,
      @FirstRow INT,
      @LastRow INT

SELECT      @PageSize = 10,
      @PageNumber = 2

SELECT      @FirstRow = ( @PageNumber - 1) * @PageSize + 1,
      @LastRow = (@PageNumber - 1) * @PageSize + @PageSize ;

select * from (select row_number() over (order by ProductID asc) as SatirNo, ProductID, ProductName   from Products) Products where (SatirNo between  @FirstRow and @LastRow)




Umarım faydalı olmuştur arkadaşlar.Bir sonraki makalemde görüşmek dileğiyle.







T-Sql Aggregate Functions - String Fonksiyonlar

Merhaba arkadaşlar.Bu makalemde sizlere T-Sql string fonksiyonları anlatmaya çalışacağım.Bizim için önceden hazırlanmış fonksiyonlardır.Tıp ki C# da ve ya başka dillerde olduğu gibi...String fonksiyonlar diğer dillerde olduğu gibi T-Sql'de de string bir ifade üzerinde belli işlemler yaparak istediğimiz sonuçları almak için kullanılır.

Bu kısa ön bilgiden sonra var olan string fonksiyonları incelemeye geçebiliriz.

1-)ASCII(char tipinde karakter): Parametre olarak verilen tek bir karakterin ascii karşılığını bize verir.


SELECT ASCII('A')

2-)CHAR(Ascii kod): Ascii kod olarak verilen değerin karakter karşılığını bize geri döndürür.

SELECT CHAR(65)

3-)CHAR(ArananKelime,AranılanKelime): Parametre olarak ilk verilen string ifadenin ikinci string ifade içerinde kaçıncı karakterden itibaren başladığını geri döndürür.Eğer bulamazsa 0 değerini geri döndürür.

SELECT CHARINDEX('Koray','Mühendis Koray')

4-)LEFT(stringİfade,KarakterUzunluğu): Verilen ilk parametredeki string ifadenin solundan başlayarak ikinci parametrede verilen karakter sayısı kadar karakterleri alıp bize geri döndürür.

SELECT LEFT('Koray Düzgün',3)

5-)LEN(StringIfade): Parametre olarak verilen string ifadenin karakter sayısını geri döndürür.

SELECT LEN('Koray Düzgün')

6-)LOWER(StringIfade): Verilen string ifadenin tamamını küçük harfe döndürür.

SELECT LOWER('Koray Düzgün')

7-)LTRIM(StringIfade): Parametre olarak verilen string ifadenin solunda kalan boşlukları temizler.

SELECT LTRIM('                  Koray Düzgün')

8-)RTRIM(StringIfade): Parametre olarak verilen string ifadenin sağında kalan boşlukları temizler.

SELECT LTRIM('Koray Düzgün'                  )





9-)REPLACE(DegisecekStringIfade,EklenecekStringIfade,ÇıkacakStringIfade): Parametre olarak verilen ilk kelimede son parametredeki ifade yerine ikinci ifadeyi ekler.

SELECT REPLACE('Koray Düzgün','Koray','Bilgisayar Mühendisi Koray')

10-)REPLICATE(StringIfade,Adet): Verilen string ifadeyi istenilen adet kadar yanyana yazar.

SELECT REPLICATE('Koray',3)

11-)REVERSE(StringIfade): Parametre olarak verilen string ifade tersine çevirip geri döndürür.

SELECT REVERSE('K.Düzgün')

12-)RIGHT(stringİfade,KarakterUzunluğu): Verilen ilk parametredeki string ifadenin sağından başlayarak ikinci parametrede verilen karakter sayısı kadar karakterleri alıp bize geri döndürür.

SELECT RIGHT('Koray Düzgün',3)



13-)SPACE(Adet): Parametre olarak verilen adet kadar boşluk karakteri geri döndürür.

SELECT 'Koray' + SPACE(2) + 'Düzgün'

14-)STUFF(DegisecekString,Baslangıç,KarakterUzunlugu,EklenecekString): Verilen ilk string ifadeden 2.parametre olarak verilen başlangıç karakterinden itibaren 3. parametre olarak verilen karakter uzunluğu kadar tüm karakterleri siler ve yerine son parametredeki string ifadeyi ekler.

SELECT STUFF('Koray Düzgün',3,5,'Koray')

15-)SUBSTRING(StringIfade,Baslangic,KarakterUzunlugu): Parametre olarak verilen string ifadeden verilen başlangıç sayısından itibaren son parametre olarak verilen karakter uzunluğu kadar olan karakterleri geri döndürür.

SELECT SUBSTRING('Koray Düzgün',4,5)

16-)UPPER(StringIfade): Verilen string ifadenin tamamını büyük harfe döndürür.

SELECT UPPER('Koray Düzgün')


Evet arkadaşlar umarım faydalı olmuştur.Bir sonraki makalemde görüşmek dileğiyle ...