C# Asynchronous Programming (Asenkron Programlama)

Merhaba arkadaşlar,

Bu yazımda C# Programlama Kılavuzu adı altında başladığım C# serimin son konusu olan Asenkron Programlama hakkında elde ettiğim bilgileri paylaşıp örnekler üzerinde pekiştiriyor olacağız. Öncelikle daha önceden de bahsettiğim ve bana referans olan “Her Yönüyle C#” kitabı ve yazarı Sefer Algan’a teşekkürlerimi sunarım 🙂 C# yazılarımda referans olarak ağırlıklı olarak bu kitabı aldım ve kafama yatmayan bazı yerleri 🙂 Microsoft dokümanından ve diğer kaynaklardan yararlandım. O yüzden C# programlama dilini ve .Net Sınıf Kütüphanesini temel düzeyde ana hatlarıyla öğrenebileceğimiz güzel bir C# serisi olduğunu düşünüyorum.

Hadi serinin son konusu olan Asenkron Programlama‘ya başlayalım.

Bu yazıda bahsedilecek konular

  • Asenkron Programlama
  • async ve await anahtar kelimeler
  • Caller Information Attribute (Nitelik)
  • C# 6.0 ile ilgili güncelleme notu

Giriş

Asenkron Programlamaya geçmeden önce asenkron kelimesinin anlamına bakalım;

Asenkron, başlama ve sona erme zamanları ayrı olan, aynı zamanda olmayan (olgular, olaylar). Asenkron programlama ise işleri parçalara bölüp bütün işleri aynı anda sürdürülmesini sağlayan bir davranış diyebiliriz. Yani programlama yaparken yazdığımız kod sürdürülürken aynı program içerisinde farklı işleri de sürdürülebilir.

.NET 1.0 sınıf kütüphanesinden bu yana eş zamanlı programlamayı ya da eş zamanlı olmayan programlamayı desteklemekteydi. C# 5.0 sürümünden önce IAsyncResult arayüzünden türetilen sınıflar yardımcı oluyordu. C# 5.0 sürümünden sonra asenkron işlemlerin daha kolay ve anlaşılır şekilde yapabiliyoruz.

Yeni yapının kalbine async ve await anahtar kelimeler bulunmaktadır. Bu iki anahtar kelime eş zamanlı metot yazma kolaylığında eş zamanlı olmayan metot yazmamıza olanak sağlıyor. async await anahtar kelimeler .Net 4.0 ile birlikte kullanılıyor. Bu iki anahtar kelimenin arka yapısında Task kullanılmaktadır.

async ve await Anahtar Kelimeler

async ve await anahtar kelimeler sayesinde C# derleyicisi kodun neresine müdahale edeceğini bilir. Derleyici bu iki anahtar kelimeyi gördüğü yerde derleme zamanında kodun asenkron yapıya dönüştürür.

  • async anahtar kelime derleyiciye metot içinde await anahtar kelime kullanılacağını bildirir.
  • async anahtar kelime kullanıldığı metotlarda await anahtar kelime kullanılmaz ise kodun yapısında bir değişiklik olmayacaktır
  • bir metodun async olarak işaretlenebilmesi için metodun geri dönüş değeri mutlaka void, Task veya Task<TResult> tipinde olmalıdır.
  • async ile işaretlenen metotlara ref veya out anahtar kelimeleri kullanılamaz.
  • async anahtar kelime derleyiciye kullanıldığı yerde asenkron işlem olacağını bildirir. await‘ten sonra kullanılacak metotların geri dönüşü mutlaka Task veya Task<TResult> olmalıdır.
  • await anahtar kelime async ile işaretlenmiş metotlar dışında kullanılamazlar

async ve await anahtar kelimelerin nasıl kullanılacağını anlamak adına hem eş zamanlı (senkron) hem de eş zamansız (asenkron) örnek yaparak bu anahtar kelimeleri örnek üzerinde pekiştirelim

Yukarıdaki örnekte sürekli BackgroudMetohd metodunun ürettiği değeri Console uygulamasında ekrana [BackgroundMethod] yazdığını görüyoruz. Senkron bir şekilde bu işlemi yaptığımız için Thread için işler parçalara bölünmedi ve haliyle ilk metodun bitmesi bekleniyor. BackgroudMetohd metodunun içinde sonsuz bir döngü olduğu için ondan sonra gelen metotlar çalışmayacaktır.

Şimdi bu yapıyı asenkron bir yapıya çevirelim ve sonsuz döngüde çalışan BackgroudMetohd metodu ile onun ardında çalışacak metotları aynı anda sürdürmesini sağlayalım.

Yukarıdaki örnekte Thread bloklanmadan hem BackgroundMethod işlemi sürdürülüyor hem de diğer işlerde paralelinde sürdürülüyor.

Async son eki ile biten metotlar IAsyncResult arayüzünden türemiş sınıflardır. Bu sayede hem Task alt yapısı ile çalışabilmesi hem de geriye dönük uyumluluk sağlanmış oluyor.

Not: Genelde asenkron programlama ile multi-thread programlama aynı şey olarak düşünülür. Bu her zaman için doğru bir bilgi değildir.

Caller Information Attribute (Nitelik)

Bazen geliştirdiğimiz uygulamalarda kimin hangi metodu veya özelliğini çağırdığı bilgisine ihtiyaç duyarız. Bu bilgiler özellikle büyük uygulamalarda bakım yapılabilirliğini (maintainability) açısından çok önemlidir. Çağrılan bilgiler uygulamadaki bug‘ların tespiti, hataların kaydedilmesi, performans ölçümü gibi konular için bazen hayati önem taşır.

C# 5.0’dan önce bu bilgileri elde etmek için System.Diagnostic isim alanı içerisinde bulunan StackTrace ve StackFrame sınıfları kullanılarak çalışma zamanında (run-time) elde edilebiliyordu. Ancak bu yapı kullanılarak call-stack bilgisini kullandıkları için performans sorunlarına sebep oluyordu.

Caller Information nitelikleri bu bilgilere ulaşabilmek için daha kolay ve okunaklı bir alternatif sunuyor.

Caller Information nitelikleri, metotların sadece opsiyonel parametrelerinde kullanılır. Bu işlemler için üç adet nitelik vardır;

  • [CallerMemberName]: çağrımı yapan metot veya özellik için bilgi verir
  • [CallerFilePath]: çağrımı yapanın kaynak kodunu içeren dosya yolu bilgisini verir
  • [CallerLineNumber]: çağrımı yapan kodun satır numarası bilgisini verir

Caller Information niteliklerinin kullanımı ile ilgili örnek yapalım;

C# 6.0 ile ilgili Güncelleme Notu

C# 5.0 ile birlikte await kullanımı catch bloklarında kullanılamıyordu. Buna göre herhangi bir catch bloğunda normal bloklar gibi await kullanılabilmektedir.

Bu yazımla C# programlama dili ve .Net sınıf kütüphanesini daha iyi anlamak için giriştiğim blog serimin sonuna gelmiş bulunmaktayım. Geriye dönük baktığım zaman gerek zaman zaman zorlandığım gerekte keyif aldığım bu serimin bitirmenin mutluluğu içindeyim açıkçası 🙂 Bundan sonra edindiğim bu bilgileri kullanarak kodlama yaparken zevkli işler yapacağıma inanıyorum 🙂

Bu yazımda Asynchronous Programming (Asenkron Programlama) hakkında elde ettiğim bilgileri paylaşmaya çalıştım. Umarım faydalı olmuştur.

Bir sonraki yazımda görüşmek üzere 🙂

Kaynaklar:

Her Yönüyle C# 7.0, Sefer Algan, Pusula Yayincilik,

https://docs.microsoft.com/tr-tr/dotnet/csharp/programming-guide/concepts/async/

C# Advanced LINQ Query Expressions

Merhaba arkadaşlar,

Bir önceki yazımda C# LINQ Mimarsine giriş yapıp LINQ Mimarisi ile kullanılan yeni özelliklere hakkında bilgi edindik. (LINQ Mimarisi ve Yeni C# Özellikleri yazıma buradan ulaşabilirsiniz)

Bu yazımda Gelişmiş LINQ Sorgu İfadeleri (Advanced LINQ Query Expressions) neler, onları ele alıp örnekler üzerinden pekiştiriyor olacağız.

Gelişmiş LINQ ifadelerine başlamadan önce bilmemiz gereken bazı bilgiler;

  • Bir LINQ ifadesi her zaman from deyimi ile başlar.
  • from deyimi ile sorgulanacak kaynak belirtilir.
  • select deyimi ile genellikle sonuçlandırılır.
  • İlk from deyimi ile opsiyonel olarak let, yine from ya da where deyimleri gelebilir.
  • Birden fazla from kullanarak birleştirme yapılabilir.
  • where deyimi filtreleme yapmak için kullanılır.
  • let deyimi sorgu içinde değişken tanımlamak için kullanılır.
  • son olarak into deyimi kullanılarak sql’deki gibi iç içe sorgu yapılabilir.
AçıklamaMetotlar
Kısıtlama Operatörleri (Restriction Operators)Where
İzdüşümü Operatörleri (Projection Operators)Select, SelectMany
Gruplama Operatörleri ( Grouping Operators)Group
Sırlama Operatörleri (Ordering Operators)OrderBy, ThenBy, Reverse
Bölümleme Operatörleri (Partitioning Operators)Take, Skip, TakeWhile, SkipWhile
Dönüştürme Operatörleri (Conversion Operators)ToArray, ToList, ToDictionary, OfType
Küme Operatörleri ( Set Operators)Distinct, Union, Intersect, Except
Group Operatörleri (Aggregate Operators)Count, Sum, Min, Max, Average, Fold
Ölçüm Operatörleri (Quantifier Operators)Any, All
Eleman Operatörleri ( Element Operators)First, FirstOrDefault, ElementAt, Single, SingleOrDefault
Ve Diğer OperatörlerConcat, SequenceEqual

Genişletilmiş metotlara aşağıdaki örnek sınıfları esas alınarak işlenecektir.

İzdüşümü Operatörleri (Projection Operators)

Elde edilen nesneyi daha sonra kullanılacak özelliklerden oluşan yeni bir forma dönüştürme işlemidir.

YöntemAçıklamaC# Sorgu İfade Sözdizimi
Selectyeni formda oluşan bir nesneselect
SelectManybirden fazla from ile oluşan yeni bir nesnebirden fazla from 

Bölümleme Operatörleri (Partitioning Operators)

Elde edilen nesneyi daha sonra kullanılacak özelliklerden oluşan yeni bir forma dönüştürme işlemidir.

YöntemAçıklamaC# Sorgu İfade Sözdizimi
TakeBelli sayıdaki elemanları alır
Skipelemanları belli sayı kadar atlatır
TakeWhileBelli koşula göre elemanları alır
SkipWhileBelli koşula göre elemanları atlatır

Sırlama Operatörleri (Ordering Operators)

Bir veya daha fazla elemanları belirtilen işleme göre artan veya azalana göre sıralar.

YöntemAçıklamaC# Sorgu İfade Sözdizimi
OrderByElemanları artan sırada sıralarorderby
OrderByDescendingElemanları azalan sırada sıralarorderby … descending
ThenByElemanları birden fazla kritere göre artan sırada sıralarorderby …, …
ThenByDescendingElemanları birden fazla kritere göre azalan sırada sıralarorderby …, … descending
ReverseKoleksiyondaki elemanları tersine çevirir

Gruplama Operatörleri ( Grouping Operators)

Her bir gruptaki elemanların ortak bir öznitelik paylaşabilmesi için verileri gruplara ayırma işlemidir.

YöntemAçıklamaC# Sorgu İfade Sözdizimi
GroupByOrtak bir özniteliği paylaşan öğeleri gruplargroup…by veya group….by…into…
ToLookupElemanları anahtara göre Lookup nesnesine (one to many ilişkisine dayalı) ekler

Küme Operatörleri ( Set Operators)

Koleksiyondaki elemanları koşula göre sonuç kümesi oluşturmak için kullanılır.

YöntemAçıklamaC# Sorgu İfade Sözdizimi
DistinctYinelenen değerleri koleksiyondan çıkarır.
ExceptKüme farkını döner. (İkinci koleksiyonda olmayan elemanlar)
Intersectİki koleksiyondaki kesişen elemanları döner.
Unionİki koleksiyonu birleştirir.

Dönüştürme Operatörleri (Conversion Operators)

Herhangi bir LINQ ifadesinin türünü değiştirir.

AsEnumerable, AsQueryable, ToArray, ToDictionary, ToList, Tolookup …

Eleman Operatörleri ( Element Operators)

Koleksiyon içindeki tek bir elemana ulaşmak için kullanılır.

YöntemAçıklamaC# Sorgu İfade Sözdizimi
ElementAtBelirtilen dizindeki elemanı döner
ElementAtDefaultBelirtilen dizindeki elemanı döner veya varsayılan değeri döndürür.
FirstKoleksiyondaki ilk elemanı döner veya koşulu yerine getiren ilk elemanı
FirstOrDefaultKoleksiyondaki ilk elemanı döner veya koşulu yerine getiren ilk elemanı döner. Böyle bir koşul yok ise varsayılan elemanı döndürür.
LastKoleksiyondaki son elemanı veya koşulu yerine getiren son elemanı döner.
LastOrDefaultKoleksiyondaki son elemanı veya koşulu yerine getiren son elemanı döner. Böyle bir koşul yok ise varsayılan elemanı döndürür.
SingleKoleksiyondan tek elemanı döner veya koşulu sağlayan tek elemanı döner. Döndürülecek eleman yoksa veya birden fazla eleman var ise InvalidOperationException hatası fırlatır.
SingleOrDefaultKoleksiyondan tek elemanı döner veya koşulu sağlayan tek elemanı döner. Döndürülecek eleman yoksa varsayılan değeri döner. Birden fazla eleman var ise InvalidOperationException hatası fırlatır

Ölçüm Operatörleri (Quantifier Operators)

Koleksiyondaki elemanların koşulu yerine getirip getirmediğini ifade etmek için kullanılır.

YöntemAçıklamaC# Sorgu İfade Sözdizimi
AllTüm elemanlar koşulu sağlayıp sağlanamadığı belirler.
AnyKoleksiyondaki elemanların bir durumu karşılayıp karşılamadığını belirler.
ContainsKoleksiyondaki elemanlar belli bir elemanı içerip içermediğini belirler.

Birleştirme Operatörleri (Concatenation Operators)

İki diziyi arka arkaya birleştirmek için kullanılır.

YöntemAçıklamaC# Sorgu İfade Sözdizimi
ConcateBir dizi oluşturmak için iki diziyi birleştirir.

Eşitlik Operatörleri (Equality Operators)

İki koleksiyonun bütün elemanları karşılıklı olarak birbirine eşit olup olmadığını kontrol etmek için kullanırız.

YöntemAçıklamaC# Sorgu İfade Sözdizimi
Sequenceequalİki dizinin eşit olup olmadığını, tüm elemanların eşit olup olmadığını kontrol eder

Birleştirme Operatörleri (Join Operators)

Birbirleriyle ilişkilendirmiş iki veri kümesi üzerinde join operatörü kullanılarak ortak öznitelik paylaşan nesnelerle ilişkilendirilmesi için kullanılır.

YöntemAçıklamaC# Sorgu İfade Sözdizimi
JoinSeçilmiş anahtara göre iki diziyi birleştirirjoin….in….on….equals….
GroupJoinSeçilmiş anahtara göre iki diziyi birleştirir ve gruplarjoin….in….on….equals….into…

Bu yazımda Gelişmiş LINQ Sorgu ifadeleri (Advanced LINQ Query Expressions) hakkında edindiğim bilgileri paylaşmaya çalıştım. Umarım faydalı olmuştur 🙂

Bir sonraki yazımda görüşmek üzere 🙂

C# LINQ Architecture and New C# Features

Merhaba arkadaşlar,

Bu yazımda C# programlama dilinde LINQ Mimarisi ve Yeni C# özellikleri neler? Bunların bize sağladığı yararlar neler ve LINQ yaklaşımını esas alarak yapabileceklerimizden bahsetmek istiyorum.

Bu yazıda bahsedilecek konu başlıkları

  • LINQ (Language Integrated Query: Dile Entegre edilmiş Sorgu Yapısı)
    • LINQ Veri Sağlayıcıları ( LINQ to Object, LINQ to SQL, LINQ to XML)
  • C# Yeni Özellikler
    • var bildirim değişkenleri ve Tip Çıkarsama (type inference)
    • İsimsiz Tipler (Anonymous Type)
    • Nesne ve Koleksiyon İlklendirme (Object and Collection Initializer)
    • Otomatik Özellik Bildirimi (Automatic Property)
    • Genişletme Metotları (Extension Methods)
    • Lambda İfadeleri (Lambda Expression)
    • Kısmi Metotlar (Partial Methods)
  • İfade Ağaçları (Expression Trees)
  • Ertelenmiş Çalışma (Deffered Execution)

LINQ (Language Integrated Query: Dile Entegre Edilmiş Sorgu Yapısı)

https://www.codeproject.com/Articles/19154/Understanding-LINQ-C

LINQ Mimarisi 3 katmandan oluşmaktadır. En üstteki katman LINQ yapısını kullanacak olan programlama dilleridir. Ortadaki katman LINQ sorgularının işlendiği katman ve en alttaki katman ise LINQ için çetişli data-source'lar mevcut ve bu data-source'lar IEnumerable <T> ve IQueryable<T> şablon tipli arayüzleri uygularlar. Bu data-soruce ile LINQ Query katmanı arasında iletişim kuran LINQ provider (sağlayıcı). LINQ Provider sayesinde LINQ sorguları veri-kaynağı tarafından anlaşılabilir hale geliyor.

C# programlama diline eklenen yeni özelliklerin temelinde yatan şey nesne yönelimli programlama ile fonksiyonel programlamayı birleştirmektir.

LINQ C# 3.0’daki en önemli yeni bir özellik diyebiliriz. Kısaca C# programlama dili ile herhangi bir üçüncü bileşene ihtiyaç duymadan dilin kendi söz-dizimi ile veriye erişimi ve veri üzerindeki işlemleri kolaylaştırmaktadır. Bahsedilen veri çok çeşitli olabilir; veri-tabanındaki ilişkisel veri olabilir, hafızada bir liste veya XML dosyası olabilir. LINQ, veri erişim mekanizmasının veri tipinden bağımsız olarak standart hale getirilmiş söz dizimi topluluğuna verilen genel bir isimdir. LINQ barındırdığı çeşitli soyutlama yapısı ile farklı veri kaynaklarına da erişim sağlayabilmektedir.

LINQ Veri Sağlayıcıları

  • LINQ to Object: Hafızada bulunan List<T> tipinde koleksiyon yapılarının sorgulanması ve işlenmesi amacı ile geliştirilmiştir.
  • LINQ to SQL: SQL Server gibi ilişkisel veri formatında veriyi tutan ortamlardaki verilere erişmek ve o veriler üzerinde işlemler yapmak için geliştirilmiştir. Literatürde bu yaklaşıma ORM (Object Relation Map) denilmektedir.
  • LINQ to XML: XML veri kaynaklarına herhangi bir parser (ayıklayıcı) kullanılmadan hızlı bir şekilde erişmek için geliştirilmiştir. Temel amacı XML tipli veriler ile çalışırken üretkenliği artırmak.

Neden LINQ

Klasik veri-tabanında veriye erişim yönetimindeki temel sorunları irdeleyecek olursak

  • Derleme sırasında sorgu kontrolü yapılamamaktadır. Kod ortamında sorgular string yapıda oldukları için sorguların yazımında da üretkenlik düşmektedir.
  • Sorgular içerisinde gevşek bağlı (loosely coupled) argümanlar bulunmaktadır. Bu yüzden çalışma zamanında veri-tipi uyuşmazlığı ile karşılaşırız.
  • Tip kontrolü yapılmadığı için çalışma zamanında hatalar meydana gelmektedir.

Platform bağımsızlığından kaynaklanan bu farklıları ortadan kaldırmak ve programcıyı veri-bağımsız hale getirmek için C# 3.0 ile birlikte LINQ yapısı geliştirilmiştir.

ORM (Object Relation Mapping) Yaklaşımı

ORM bir başka ismi ile O/R Mapping, ilişkisel veri-tabanını ile nesneye yönelik programların arasında bir tür köprü görevini üstlenen ve ilişkisel veri-tabanındaki bilgilerimizi yönetmek için nesnel modellerimizi kullandığımız bir tekniktir.

Klasik veri erişim sorunlarından sonra LINQ erişim sayesindeki kazanımlar

  • O/R Mapping yaklaşımı sayesinde nesnel düşünmekten feragat etmeden veri erişim işlemlerini gerçekleştirmek
  • Tip Güvenliğini sağlamak
  • Veri-tabanı kavramını nesnel olarak tanımlamak
  • Herhangi bir sorgu yazmadan veri-tabanına erişim sağlayabilmek
  • söz-dizimi olarak hatalı bir sorgu yazmamızı engelliyor.

LINQ to Object Mimarisi

LINQ to Object sağlayıcısı hafızada bulunan ve IEnumerable<T> arayüzünü uygulayan bütün koleksiyonlarda uygulayabileceğimiz ve .NET 3.5 ile birlikte gelen yapıdır.

Yukarıdaki örnek uygulamada aslında for döngüsü ile de bu işlemi yapabilirdik. Ancak LINQ ile bu işlem hem daha basit hem okunaklı olmaktadır. yukarıda from, where ve select gibi LINQ yapıları ile tıpkı SQL ortamında sorgulama yapılabilir.

Bu yapılar ve daha fazlası aslında aşağıdaki gibi de kullanabilmekteyiz.

Bu metot yapılar genişletme metotları (extension method) sayesinde oluyor. Yukarıdaki kod bloğunun çalışabilmesi içinde

bildirimin kod içerisinde olması gerekiyor.

Select ve Where metodundaki parametreler aslında birer delegate olduğunu bilmek gerekir. Bu sayede daha eski CLR 2.0 yapısına dönüştürülürse aşağıdaki çağrım olacaktır.

C# Yeni Özellikler

var bildirimli Değişkenler

C# 3.0 ile birlikte bir metot içerisinde tanımlanacak değişkenler tipleri bildirilmeden tanımlanabilmektedir.

Dile eklenen var anahtar sözcüğü sayesinde değişkene atanan değerin tipinden çıkarsama (type inference) yapılarak derleme aşamasında IL içerisine gerçek tipli bildirim eklenir.

Bu noktada bir değişkeni object olarak tanımlamak ile var bildirimi ile tanımlamak arasında hiçbir benzerlik yoktur. Çünkü object ile tanımlanan değişkenlerin tür kontrolleri ve ayrışımı çalışma sırasında dinamik olarak yapılır. var ile bildirimlerde ise bu işlem derleme zamanında olmaktadır.

var anahtar bildiriminin dile eklenmesinin temel nedeni yukarıdaki basit veri tipleri tanımlanırken değil de özellikle şablon tipli karmaşık veri tiplerinin tanımlanmasıdır. Özellikle LINQ içerisinde Select ifadesi ile geriye döndürülen tipin ne olduğu belli olmadığı durumlarda (anonymous type) var bildirimi kullanılması kaçınılmazdır. Zaten bu özellik daha çok bu amaç için eklenmiştir.

yukarıdaki örnekte Select metodunda geri döndürülen nesnenin adı belli değildir. Bu durumda geriye isimsiz sınıf dönmüştür. Bu durumda isimsiz sınıfları var bildirimine atamalıyız.

var anahtar kelimesi ile bildirilen değişkenlerin kısıtları;

  • var ile bildirilen değişkenler sadece local değişkenler olabilir. Yani bir sınıf üye elemanı olamaz
  • var ile bildirilen değişkene ilk değer atama işlemi zorunludur. Aksi durumda tip çıkarsaması yapamayacağından derleme zamanında hata oluşur.
  • Bir metodun herhangi bir parametresi yada geri dönüş değer var tipinde olamaz
  • var ile bildirilen değişkene sonradan farklı türden değişken atanamaz

Dizi Tiplerinin Çıkarsama Yolu ile Belirlenmesi (Type Inference)

C# 3.0 ile birlikte gelen yeniliklerin bir tanesi dizi tiplerinin dizi içerisinde bulunan elemanların tiplerinden çıkarabilmesidir.

Dizi elemanları aynı tipten veya bilinçsiz (implicit) bir şekilde birbirine dönüştürülebilen tipten olması gerekiyor.

İsimsiz Tipler (Anonymous Types)

C# 2.0 ile birlikte gelen isimsiz metotlardan sonra C# 3.0 ile birlikte LINQ yapısında kullanabilmek için isimsiz tipler gelmiştir. Öyle bir veri-tipi düşününki içinde birbiri ile ilişkili özellik olsun ama adı olmasın 🙂

İsimsiz tip tanımlama söz-dizimi

ILDASM aracı ile IL kodlarına baktığımızda IL kodlarına isimsiz bir tipin enjekte edildiğini görürüz. (<>f__AnanymousType0’2′)

İsimsiz Tipler diğer .NET sınıflarında olduğu gibi otomatik olarak object türünden türetilmiş bir sınıf olarak tanımlanır.

İsimsiz tiplerin en önemli kullanım yeri LINQ yapısıdır. Özellikle Select metodu ile geri döndürülen nesne eğer koleksiyon tipinden farklı ise işe yaramaktadır.

İsimsiz tipler ile ilgili diğer bir durum ise aynı kalıba uygun nesnelerin birbirine atanıp atanamayacağı. Aynı program içinde aynı özellik desenine sahip (isim ve tip bakımından) isimsiz tip nesneler birbirine atanabilmektedir.

Nesne ve Koleksiyon İlklendirme

C# 3.0 ile birlikte Nesne ve Koleksiyonları çok daha kolay bir şekilde oluşturabiliyoruz.

Nesne İlklendirme

Sınıflara ait nesneleri yaratırken yapıcı metot (constructor) kullanıyoruz. Eğer yazdığımız yapıcı metotların tek görevi özelliklerin veya değişkenlerin aramasını yapması ise bunu nesnemiz oluştururken süslü parantezler ile özelliklere ilk değerlerini yapabiliriz.

Koleksiyon İlklendirme

Aynı Nesne İlklendirmede olduğu gibi Koleksiyon nesnemizi oluştururken elemanlarını da süslü parantezler içinde belirleyebiliriz.

Sondaki Koleksiyon İlklendirme C# 6.0’dan itibaren geçerli olduğunu hatırlatayım!

Otomatik Özellik Bildirimi (Automatic Property)

C# 3.0 ile birlikte özellik tanımlama biçimi daha kolay hale geldi. Yalnızca erişim kontrol altına alınmak istendiği senaryolarda get ve set bloklarını tek tek yazmak ve özelliğe ait değişkeni tanımlamaya gerek yok.

Otomatik özellikler daha çok bir sınıfın özellik havuzu şeklinde kullanılması durumunda faydalı olmaktadır. Bu durumda C# derleyicisi derleme aşamasında otomatik özelliğe ait get ve set bloklarını IL koduna yerleştirir.

Department sınıf bildirimini içeren IL kodu aşağıdaki gibidir. Title değişkeni <Title>k__BackingField isminde adlandırılmış ve get ve set metotları da eklenmiş durumda.

Otomatik özellik tanımlama daha çok XML ve SQL yapısında verilere erişmek için kullanılan eşleştirme sınıflarının ( mapping class) bildiriminde kullanılır.

C# 6.0 sürümü ile birlikte otomatik özellik bildirimine yeni bir özellik gelmiştir. Buna göre otomatik özellik bildirimine aynı sınıflar değişkenlerinde olduğu gibi ilk değer ataması yapılabilmektedir.

Genişletme Metotları (Extension Methods)

Genişletme metotları LINQ mimarisi için nesne yönelimli programlamanın dışında olan bir özellik eklenmiştir. Genişletme metotları mevcut bir veri tipine yeni bir metodun eklenmesini olanak sağlar. Böylece türetme olmadan ve mevcut tipin kullanılmasını engellemeden aynı tiplere yeni metotlar eklenebilir. Yine bu özelliğin çıkış noktası LINQ yapısında bulunan Select ve Where gibi fonksiyonların mevcut koleksiyonlarla çalışmasına olanak sağlamaktır.

IEnumerable<T> üzerinde çağrılan genişletilmiş metotlar bulunmaktadır. Aşağıda List<string> nesnesi üzerinde Where metodunu çağrıldığını görebiliriz. Where metodu aslında genişletme metodudur ve IEnumerable<T> üzerinden çağrılmaktadır.

Where genişletme metodunun prototipine baktığınızda şablon tipli olduğunu görüyoruz. Where metodu TSource tipinde bir şablon tip parametre alıyor ve geri dönüş olarak yine bu tipte bir koleksiyon tabanlı nesne dönüyor. İlk parametre this ile bildirilen IEnumerable<TSource> ile asıl genişletilmek istenen kaynağı bildiriyoruz. İkinci parametre olan predicate yaptığımız koşulu bir temsilci vasıtasıyla gönderiyoruz. Bu sayede filtrelemek koşuluna göre geriye bir koleksiyon dönecektir.

System.Linq.Enumerable isim alanında bulunan bazı extension metotlar.

Genişletme metotları ile ilgili önemli durumlar;

  • Genişletme metotları yapı, sınıf ve arayüzlere uygulanabilir
  • Genişletme metotların bildirimi static bir sınıf içinde tanımlanmalıdır.
  • Genişletilecek tip bildirimi, Genişletme metodunun ilk parametresi olmak zorundadır ve önüne this anahtar sözcüğü gelmelidir.
  • Genişletme metoduna erişilebilmesi için ilgili yerde genişletme metoduna ait sınıfın erişilebilir olması gerekir.
  • Sınıfın genişletme metodunun prototipine uygun başka bir metodu varsa çağrım sırasında öncelik sınıfın kendi metodudur.
  • Genişletme metotları da normal metotolar gibi aşırı yüklenebilir (overload)
  • Bir tipe farklı static sınıflar içinde genişletme metodu eklenebilir. Bu durumda farklı noktalardaki metotların imzaları farklı olmalıdır.
  • Genişletme metotları sadece C# diline ait değildir.
  • Taban sınıfa eklenen genişletme metodu, taban sınıftan türeyen sınıflardan da erişmek mümkün. Örneğin object sınıfına eklenmiş olan genişletme metodu bütün tiplerde gözükür.

Genişletme metotları LINQ yapısı dışında da kullanışlı olabilecek bir özelliktir. Kendi genişletme metotlarımızı da yazabiliriz.

Genişletme metotları normal yoldan da çağrılabilir.

Lambda İfadeleri (Lambda Expression)

Lambda ifadeleri C# 3.0 ile birlikte eklenmiş en önemli özelliklerden biridir. Lambda ifadeleri ile LINQ yapısını kolay ve anlaşılabilir olarak kullanılabilmesi için olan bir özelliktir. Lambda ifadeleri fonksiyonel programlamada kodun bir veri olarak temsil edilmesini sağlayan ifadelerdir. Lambda ifadeler C# yeni olmasına rağmen aslında Lisb, Python ve Schema gibni programlama dillerinde var olan bir özelliktir.

Lambda ifadelerin algoritmayı daha doğrusu kodu bir veri kaynağı olarak görmesinden kaynaklı gücü sayesinde algoritmaların daha hızı yazılmasını sağlar.

Peki nedir bu Labmda? C#’ta lambda ifadeler delegate değimiz yani temsilcilerle doğrudan ilgilidir. Lambda ifadeleri delegate nesnesi bekleyen fonksiyon parametrelerini metot bildirimi yapmaksızın kullanmamızı sağlıyor.

FindAll metodu aslında bir delegate parametresi bekliyor. Lambda ifadesi sayesinde temsilciler birer veriymiş gibi fonksiyonlara parametre olarak gönderilebilir.

Tanımlama biçimleri

Kalıp: (parametreler) => (ifade gövdesi) ifade gövdesinde üretilen sonucun tipi neyse geri dönüş değeri o olur.

Expression Lambda

(input-parameters) => expression

Statement lamda

(input-parameters) => { <sequence-of-statements> }

Lambda Gövdeli Metot ve Özellik Bildirimi

C# 6.0’dan itibaren eğer set bloğunda yazacağımız kod ya da metot gövdesinde yazacağımız kod 1 veya 1^den az ise lambda ifadelerini kullanabiliriz.

C# geliştiricilerinden gelen yoğun istek üzerine C# 7.0 versiyonu ile birlikte metot ve özelliklere ek olarak lambda gövdeli yapıcı metot, yıkıcı metot ve get set blokları için kullanabiliriz.

Kısmi Metotlar ( Partial Methods)

C# 2.0 ile birlikte bir sınıfı birden fazla fiziksel dosyaya bölen kısmi sınıflar vardı. Böylece otomatik olarak yazılan kodlar ile programcının yazmış olduğu kodlar birbirinden ayrılmış oluyordu.

Kısmi metot kavramı C# 3.0 ile birlikte gelen bir kavramdır. Kısmi metotlar yine özellikle otomatik olarak üretilen kod blokları ile bo kod bloklarının kullanan istemci uygulama arasında entegrasyon (mesaj alaış-veriş) sağlanmaktadır. Kısmi metotlar şu anda daha çok LINQ ifadeler ile (LINQ to SQL) sıkça kullanılmaktadır.

Temel kullanım amacı Entity denilen tabloyu temsil eden yapılarda meydana gelen değişiklerde uygulamayı haberdar etmesidir. Normal şartlar bu event mekanizması ile yapılabilir ancak bu hem maliyetli olacaktır hem de uygulaması zor olacaktır.

Kısmi metotlar uygulamada otomatik olarak kod üretilen bir yapı var ise anlamlı olur!

Bu yapıya örnek verelim;

Otomatik olarak üretilen bu kod aşamasından sonra PersonManager partial sınıf oluşturulup kısmı metotlar bildirilebilir.

Bu aşamada kod derlendikten sonra çalışma zamanında ilgili kısmı metotlar çalışacaktır.

Kısmi metotlar ile ilgili bilinmesi gerekenler

  • Kısmi metotlar sadece kısmi tipler için geçerlidir.
  • Kısmi metotların gövdesi her zaman olmak zorunda değildir. Gövdesi olmayan kısmi metotlar IL dahil edilmezler.
  • Kısmi metotlar partial olarak bildirilirler
  • Kısmi metotların geri dönüş değeri void olmak zorundadır.
  • Kısmi metotlar override, virtual, abstract, new, sealed anahtar sözcüğü ile bildirilemezler
  • Kısmi metotlar static olabilirler
  • Kısmi metotlar erişim belirleyicileri ile belirlenmezler (Varsayılan olarak private)
  • Kısmi metotların parametreleri ref, params, this gibi anahtar sözcükleri ile tanımlanabilirler

LINQ to SQL ile Veritabanı Sorgulama

LINQ mimarisi genişleyebilir bir mimaridir. LINQ ifadeleri arka planda IQueryable arayüzü ile uyumlu nesneler üretir. Bu arayüz içerisinde LINQ ifadeleri ağaç şeklinde oluşmasını sağlayan Expression nesnesi bulunmaktadır. IQueryProvider isimli arayüz sayesinde dinamik olarak sorgu cümleleri çalışma zamanında oluşturulabilir.

LINQ to SQL yapısında sorgular çalışma zamanında t-sql yapısına çevrilerek veri-tabanı üzerinde direkt olarak sorgulama yapılabilmesine olanak sağlar. Bu gelişme araçları kullanılarak üçüncü parti firmalar ya da kişiler kendi özgü LINQ sağlayıcılarını geliştirmişlerdir.

Linq To SQL Örnekleri

LINQ to SQL yapısı ile ilgili sınıflar, nitelikler ve arayüzler System.Data.Linq ve System.Data.Linq.Mapping isim alanları altındadır.

Yukarıdaki sorgu ifadesinde foreach iterasyonu başladığında IQueryProvider nesnesi devreye girerek LINQ sorgu ifadesinden t-sql sorgu cümlecikleri oluşturur. Yukarıdaki ifadeden sonra üretilen t-sql sorgusu;

LINQ to XML Altyapısı

LINQ mimarisinin XML verilerini sorgulama ve üzerinde işlem yapması için uyarlanmış versiyonudur. LINQ to XML ile ilgili sınıfların tamamı Syste.Xml.Linq isim alanındadır.

LINQ to XML sınıfları yardımıyla XML verisi hazırlama

Oluşan Xml

İfade Ağaçlar (Expression Trees)

LINQ mimarisinin genişleyebilir olmasının altında yatan şey .NET Frameowrk 3.5 ile birlikte gelen ifade ağaçlarıdır. İfade ağaçları sayesinde çalıştırılabilir kod ağaç yapısı şeklinde veri olarak bellekte saklanır. Bu sayede LINQ sorgu ifadeleri derleme zamanında veri olarak ifade edilir. Dolayısıyla çalışma zamanında bu ağaç yapısı çözümlenir ve üretilmesi gereken kod (sql, xpath ya da metot çağrımı) belirlenir.

Kısacası LINQ mimarisinin genişleyebilir yapıda sunabilmesini sağlayan ifade ağaçlarıdır. İfade ağaçlarını temsil eden sınıflar System.Linq.Expression isim alanında bulunurlar.

Expression yapıları için kod örneği

yukarıdaki örnekte Expression yapısı kullanılarak lambda yardımı ile x değerini karesi alınıyor. elimizde run-time çalışacak ağaç yapısı artık mevcut. Daha sonra ağaç yapısı derlenerek temsilciye aktarılıyor ve bu sayede elimizde artık bir sayının karesini alabilen squareFunc metodu oluşuyor.

Expresison yapısını kullanılarak if-else-then bloklarına sahip kodlarda yapmak mümkün. Expresison sayesinde dinamik kodlar yazılabilir.

Expression yapıları ile dinamik kod üretmekte mümkün.

Ertelenmiş Çalışma (Deferred Execution)

LINQ ile birlikte gelen ağaç yapısı sayesinde LINQ sorguları kod içerisine geçtiği noktada icra edilmezler. LINQ sorgularında geri döndürülen IQueryable arayüzüne sahip nesne kullanıldığı ilk noktada çağrılır. İlk kullanımdan kasıt; foreach itereasyonu veya metot çağrımı olabilir. Bu duruma ertelenmiş çalışma (Deferred Execution) denir.

Bunu daha iyi anlamak için örnek üzerinden gidelim. Elimizde IQueryable türünde verilerimiz var ve LINQ yapısı ile o veriler içinden belirlediğimiz alanı getirmek istiyoruz. Filtreleme yaparken filtrelenecek alanı değişkene (companyName) atayacağız ve LINQ sorgusu bittikten sonra kısıt değişkeninin değerini değiştirip foreach döngüsü ile en son hangi kısıt değeri ile LINQ sorgumuzun filtrelendiğini Console uygulamasına yazdırıyor olacağız.

Yukarıdaki örnekte ertelenmiş çalışma mekanizmasına göre sorgulama işlemi foreach iterasyonunda gerçek anlamda çalışacağı için companyName değişkenine tam o noktada değeri atanmaktadır. Yani companyName değeri “Trey Researc” olan şirket dönecektir.

Eğer ertelenmiş çalışma mekanizmasını devre dışı bırakmak istiyorsak LINQ sorgusunun sonucunda dönen değer üzerinden ToList(), ToDictionary() gibi metot çağrımı yapmalıyız.

Ertelenmiş çalışma mekanizmasını dere dışı bıraktıktan sonra companyName değeri olan “Coho Winery” listelendiğini görürüz. Yani ToList() yardımı LINQ sorgusu icra ediliyor.

Bu yazımda C# LINQ Mimarisi ve Yeni Gelen C# Özellikler hakkında edindiğim bilgileri paylaşmaya çalıştım. Umarım faydalı olmuştur 🙂

Bir sonraki yazımda görüşmek üzere 🙂

Kaynaklar:

Her Yönüyle C# 7.0, Sefer Algan, Pusula Yayincilik

https://docs.microsoft.com/tr-tr/dotnet/csharp/programming-guide/concepts/linq/

C# XML İşlemleri ve System.Xml

Merhaba arkadaşlar,

Bu yazımda XML Belgesi hakkında temel düzeyde bilgilenip, C# dili ile System.Xml isim alanında bulunan yapıları kullanarak XML belgelerini nasıl düzenleyeceğimizi ve XML belgesindeki bilgileri nasıl elde edebileceğimizi ele alacağız.

.Net Platformunda XML’nin (Extensible Markup Language) yani Genişletilebilir İşaretleme Dili önemi büyüktür. Hem Framework konfigürasyon dosyasının çoğu XML tabanlıdır hem de ADO.NET gibi büyük bir kütüphane XML ile iç içe çalışmaktadır. XML yeni neslin iletişim dilidir ve farklı platformların birbirleri ile haberleşirken bu dil kullanılıyor. Yani XML bu dil için haberleşme aracı olmuştur. Bu nedenle XML herhangi bir platforma bağlı kalmaması ve W3C standartları tarafından desteklenmesinin büyük payı vardır.

XML standart olmasından dolayı birçok uygulama alanı gelişmiştir. Farklı sistemler arası haberleşmeyi sağlayan Web Servisleri uygulama alanlarının en önemlisidir. Web Servisleri sayesinde İnternet protokolü dediğimiz HTTP üzerinden XML yardımıyla bir sunucudaki metodu çalıştırıp metodun geri dönüş değerini aradaki çeşitli katmanları kullanarak XML formatında elde edebiliriz.

XML bir programlama dili değildir. XML belgelerini biçimlendirilmiş metin tabanlı veri depolama işine yarayan belgeler şeklinde nitelendirebiliriz. Veritabanı sunucuları henüz piyasa yokken metin tabanlı bilgi saklama yöntemleri kullanılırdı.

XML Belgeleri

Basit bir XML dosyası yapısı

XML belgesinde her veri, kapanan ve açılan etiketler arasında yazılmıştır. Belgenin ilk satırında çeşitli bildirimler yapılmaktadır.

Her XML dosyasının mutlaka bir kök elemanı vardır. Yukarıdaki örnekte kök eleman

Kök elemanı olmayan bir XML belgesi geçerli değildir. Diğer bütün elemanlar kök elemanın içinde bulunur. Tıpkı bir ağaç yapısı gibi.

foods etiketinde 2 ayrı menuden oluşmaktadır. menu etiketinde de 3 ayrı elemandan oluşmaktadır.

menu etiketinde “name” isminde bir niteliği vardır. Bu niteliğin değeri ise “Day-1”, “Day-2” şeklindedir.

Yukarıdaki XML belgesinin İnternet tarayıcısında görünümü aşağıdaki gibidir.

System.Xml İsim Alanı

XML belgeleri üzerinde işlem yapmak için geliştirilmiş sınıflar System.XML isim alanında bulunur. Bu isim alanında birçok sınıf vardır.

XmlReader: XML belgelerinden verileri okumamız için tasarlanmış bir sınıftır. Tamponlama mekanizması ile çalışmaktadır ve sadece ileri yönlü okuma yapabilir.

XmlWriter: Bir akıma ya da dosya sistemine XML verilerini kaydetmek için kullanılır. (Sadece ileri yönlü okuma yapabilir)

XmlTextReader: XML belgelerinden sadece ileri yönlü okuma yapabiliyor ve XML belgelerine bir akım gibi (stream) erişmemizi sağlar

XmlTextWriter: XML akımlarını dosya sisteminde oluşturmak için kullanılır.

XmlNode: XML belgesindeki tek bir düğümü ifade etmek için kullanılır.

XmlNodeReader: Bu sınıf okumak için bir düğüm noktasını kaynak olarak alır.

XmlDocument: Bir XML belgesinin belleğe bir ağaç gibi yüklenmesini ve bu ağaç üzerinde çeşitli işlemler yapabilmesini sağlar.

Hazırladığımız XML belgesini okuyup düğümlerle ilgili çeşitli bilgiler eden program:

Programdan çıktısına baktığımızda .xml uzantılı dosyamızda bütün elemanların adı ve sahip oldukları nitelikleri yazdırabildik. XmlTextReader sınıfının Name özelliği ilgili düğümün etiket ismi, Value özelliği ise ilgili düğümün değerini vermektedir. Düğümlerde eleman olmak zorunluluğu yok bu yorum satırı da olabilir veya komut bildirimi de.

System.Xml isim alanında bulunan XmlNodeType numaralandırıcı türündendir ve bir özelliği de Element’tir. Diğer semboller ise;

AttributeCDATAComment
DocumentDocumentFragmentDocumentType
ElementEndElementEndEntity
EntityEntityReferanceNone
NotationProcessingInstructionSignificiantWhitespace
TextWhitespaceXmlDecleration

Programlama yoluyla XML dosyalarını oluşturmak için XmlTextWriter sınıfını kullanıyoruz.

Oluşturduğumuz XML Belgesinin son hali

DOM (Document Object Model)

XmlDocument sınıfı ile W3C’nin DOM denilen modelini destekleyen XML yapısını kullanbiliriz. XmlDocument sınıfı ile bir Xml belgesi belleğe yüklenir ve bir DataSet gibi üzerinde işlemler yapılıp tekrar Xml belgesine güncelleme yapılır. XmlDocument ile XML belgesi sisteme bir ağaç şeklinde yüklenip çeşitli sınıflar yardımı ile her bir düğüm (element) elde edilip üzerinde işlemler yapılabilir.

XmlDocument ile çalışıldığında sıkça kullanılan iki sınıf; XmlElement ve XmlAttribute sınıflarıdır. Bu sınıflar sırasıyla elemanı ve niteliği temsil etmek için kullanılır. XmlDocument nesnesini oluşturabilmek için için bir yol veya akım (stream) gereklidir. XmlDocument nesnesi bellekteki verileri temsil etmektedir. XmlDocument nesnesine XML belgesini yükleyebilmek için de XmlTextReader sınıfına ihtiyacımız olacak.

Sık Kullanılan XmlDocument sınıfının metot ve özellikleri:

Attributesİlgili düğüme ilişkin bir nitelik koleksiyonu döndürür. Bu koleksiyon türü XmlAttributeCollection‘dır
ParentNodeBir düğüme ilişkin XmlNode sınıfı ile ilişkilendirilmiş ana düğümü verir
HashChildNodesEğer ilgili düğüm başka yavru düğüm (child node) içeriyorsa true değerini verir.
FirstChildİlgili düğüme ilişkin ilk yavru düğümü XmlNode türünden verir.
LastChildİlgili düğüme ilişkin son yavru düğümü XmlNode türünden verir.
ChildNodesİlgili düğüme ilişkin yavru düğümleri bir XmlNodeList türünde verir.
NextSiblingÜzerinde çalışılan düğümün hemen sonrasındaki düğümü verir
PreviousSiblingÜzerinde çalışılan düğümün hemen öncesindeki düğümü verir.
InnerTextBir düğüm içerisinde yavru düğümleri ve varsa bu düğümlerin değerlerini verir.
InnerXmlBir düğüme ilişkin verileri ve yavru düğümleri XML etiketleri ile beraber string türünde verir
OuterXmlBir düğüme ilişkin bilgileri XML etiketleri ile beraber string türünden verir. Bu özellikte yavru düğüm alınmaz!
NameBir düğümün ismini verir
ValueBir düğümün değerini verir
NodeTypeDüğümün hangi tipte olduğunu XmlNodeType numaralandırması ile verir

XmlDocument sınıfının kullanımına örnek bir uygulama

Bu yazımda System.Xml isim alanında bulunan yapılarla birlikte XML belgelerini kullanmaya çalıştık. System.Xml isim alanı ile ilgili edindiğim bilgileri paylaşmaya çalıştım . Umarım faydalı olmuştur 🙂

Bir sonraki yazımda görüşmek dileğiyle

Kaynaklar:

Her Yönüyle C# 7.0, Sefer Algan, Pusula Yayincilik

https://docs.microsoft.com/en-us/dotnet/api/system.xml?view=netframework-4.8

C# ADO.NET ile Veritabanı İşlemleri

Merhaba arkadaşlar,

Bu yazımda C# ile birlikte veritabanı işlemlerini ele almaya çalışacağız. Bunu yaparken de günümüzde güncel kullanılan veritabanı yaklaşımları (EntityFramework ORM vs…) ile değil de ADO.NET kütüphanesini kullanarak yapmaya çalışacağız. Yani System.Data isim alanında bulunan yapıları ele alıp bu yapılar hakkında bilgilendikten sonra veritabanı ile ilgili temel düzeyde işlemler (crud) yapıyor olacağız.

ADO.NET kütüphanesini kullanarak veritabanı işlemlerini yaparken hazır veritabanı kullanacağız. Bu veritabanı açık kaynak olan Northwind veritabanı olacaktır. Northwind veritabanı örneğini bu kaynaktan indirebilirsiniz. ( Northwind veritabanı Microsoft’un sağlamış olduğu ücretsiz içerisi dolu bir veritabanı örneğidir)

ADO.NET‘e giriş yapıp, System.Data isim alanında bulunan yapıları incelemeye başlayalım:

ADO.NET ile Veritabanı İşlemleri

ADO.NET, veritabanlarındaki bilgileri elde etmek veya veri tabanında bulunan verileri değiştirmek için geliştirilmiş bir ver erişim aracıdır. ADO.NET .NET sınıf kütüphanesindeki System.Data isim alnındaki sınıfların tamamını temsil eder. Kısace ADO.NET .NET platformu için geliştirilmiş, offline çalışabilen, web uygulamalar gibi n-katmanlı uygulamalarda büyük kolaylık sağlayan veri erişim teknolojisidir.

ADO.NET modeli ile veriye erişim olarak iki ana metot kullanılır

  • Online Erişim (Connected Access)
  • Offline ERişim (Disconnected Access)
  • ADO.NET iki yeni nesne modeli sunar. Bunlar DataSet ve DataAdapter nesneleridir.
  • ADO.NET modeli ile yüksek performans sağlanır
  • Doğrudan XML Desteği verir.

DataSet, veritabanında bulunan bir veya daha fazla tablonun içinde barındırdığı tablolar koleksiyonudur.

ADO.NET veri erişimi olarak iki tür destek verir: birincisi SQL Server ile yüksek performanslı erişim, ikincisi ise OLEDB protokolünü destekleyen diğer veritabanlarına bağlanmaktır.

ADO.NET Nesne Modeli

ADO.NET kapsamındaki bütün sınıflar System.Data.Dll isimli tek bir assembly’de toplanmıştır.

System.DataADO.NET in temel isim alanıdır. Veriyi sembolize eden veri türleri burada bildirilmiştir. Kısacası ADO.NET mimarisinin temel yapı taşlarını oluşturan sınıflar bu isim alanında bulunur.
System.Data.CommonBu isim alanı managed provider dediğimiz veri erişim kanalları kullanan sistemlere yönelik sınıfları içerir
System.Data.OleDbOLEDB protokolünü destekleyen veritabanı sistemlerine erişmek için kullanılan sınıflar bu isim alanında bulunur
System.Data.SqlClientMS SQL Server için özel geliştirilmiş OLEDB protokolünü destekleyen veri tabanına bağlanmak için kullanılan sınıflar bu isim alanında bulunur
System.Data.SqlTypesBu isim alanında bulunan veri tipleri, MS SQL Server içinde desteklenen doğal veri türlerini içerir.

Veritabanına bağlanmak

Bir veri kaynağına erişmek için veri bağlantısına ihtiyacımız vardır. Bu bağlantıda bağlantı türü ve bağlantının yapılacağı veri kaynağının türü belirtilir. Veri kaynağı olan bağlantıyı sembolize eden sınıflar SqlConnection ve OleDbConnection’dır.

Örnek uygulamalarda Veri-tabanına bağlanmak için OleDbConnection sınıfını kullanacağız. Bunun sebebi OleDbConnection sınıfının Hem SQL Sunucusuna hem de diğer veritabanlarına bağlanabiliriz.

SQL Server sunucusuna erişmek için özelleştirilmiş SqlConnection ve OleDb sınıfı ile veri tabanına bağlanma

Not: OleDb ile hem SQL Sunucusuna hem de diğer veritabanlarına bağlanabiliriz!

OleDbCommand ve OleDbDataReader

OleDbCommand nesnesi bir veri kaynağındaki tablodan SQL cümleciği kullanarak sorgulama yapmamızı sağlar. OleDbDataReader sınıfı ise OleDbCommand nesnesi ile çalıştırılması durumunda elde edilen sonuçları okumak için kullanılır.

OleDbCommand nesnesini bir SQL sorgu ve bağlantı nesnesi ile oluşturabiliriz.

OleDbCommand nesnesini CommandType özelliği ile komutun ne şekilde etkileneceğini bildirebiliriz. CommandType numaralandırması ile bu özellik Text, StoredProcedure ya da TableDirect olacak şekilde ayarlanabilir.

OleDbCommand nesnesi ile veri tabanındaki Stored Procedure (kaydedilmiş sorgu) çalıştırabilir ve parametreleri geçebiliriz.

OleDbCommand üzerinden bir komutu çalıştırmak için 4 farklı metot kullanılabilir.

ExecuteNonQuery: Bu metot ile genellikle veri-tabanındaki kayıtları değiştirmek, silmek ya da güncellemek için kullanırız. Geri dönüş değeri etkilenen kayıt sayısını ifade eder.

ExecuteScalar: Bu metot ile veri-tabanından tek bir değer elde edilir. Örneğin tablodaki kayıt sayısını elde etmek için kullanılan COUNT özelliğinde kullanabiliriz.

ExecuteReader: Bu metot ile genelikle SQL Select sorgularında sıklıkla görülür. Select komutundan sonra elde edilen verileri okumak için kullanılır.

ExecuteXmlReader: Bu metot sadece SqlCommand ile uygulanabilir. SQL Server verileri XML şeklinde elde etmek için çeşitli komutlar sağlamıştır.

Dataset, DataAdapter, DataTable, DataRow, DataColumn

DataSet, veri kaynağından bağımsız olarak veriler üzerinde işlem yapmamıza ve gerektiğinde DataAdapter yardımı ile DataSet üzerindeki verileri tekrar veri tabanına aktarmamızı sağlar.

DataAdapter, veri kaynağı ile DataSet nesneleri arasındaki bağlantıyı sağlar.

DataTable, bir veri kaynağındaki tablolara benzer. Yani bir DataTable nesnesinde sütunlar ve verileri içeren kayıt satırları içermektedir. DataTable nesnesinin columns özelliği ile tablodaki sütunlar DataColumn koleksiyon şeklinde verilir. Aynı şekilde Rows özelliği de tablodaki satırları bir DataRow koleksiyonu şeklinde verir.

DataColumn özelliği bir tablodaki sütunları ifade eder ve temsil edilen bir sütunun veri türü C#’ta herhangi bir veri türü olabilir.

DataRow nesnesi ise bir tablodaki satırları temsil eder.

Bu özellikleri kullanarak veri tabanından istediğimiz verileri alıp ekrana yazdırıyoruz.

ADO.NET 2.0 ve DbProviderFactory (Veri Sağlayıcı Bağımsız Erişim)

ADO.NET 2.0’a eklenen soyut nesneler ile yapılmaktadır. ADO.NET için farklı veritabanı sistemleri ile çalışan farklı nesneler bulunmaktadır. Örneğin SqlConnection, OleDbConnection, OracleConnection gibi.

Veri tabanı sistemlerine erişirken hem veritabanı bağımsızlığı sağlamakj hem de bağlanma sırasında kendi sağlayıcılarını (provider) kullanarak perofrmanstan ödün vermeyerek yeni bir sistem geliştirilmiştir. Bu sistem literatürde abstract factory (soyut fabrika) denilen bir tasarım deseni ile gerçekleşmiştir. .Net 2.0 içerisinde 5 adet DbProviderFactory nesnesi bulunmaktadır.

Önemli: Output'ta 2 DbProviderFactory olmasının sebebi çalışılan bilgisayarda SqlClient ve OleDb kayıtlı olduğu için.

Bu yazımda ADO.NET kütüphanesi ile temel veritabanı işlemleri nasıl gerçekleştiğini inceledik. ADO.NET hakkında edindiğim bilgileri paylaşmaya çalıştım. Umarım faydalı olmuştur 🙂

Bir sonraki yazımda görüşmek dileğiyle

Kaynaklar:

Her Yönüyle C# 7.0, Sefer Algan, Pusula Yayincilik

https://docs.microsoft.com/tr-tr/dotnet/framework/data/adonet/

C# (yield)

Merhaba arkadaşlar,

Grup nesnelerini yönetirken ihtiyacımıza göre geliştirdiğimiz koleksiyon tabanlı nesnelerin foreach yapısında çalışabilmesi için IEnumerable arayüzünü uygulamak zorunda kalıyorduk .Bu işlem standart olsa da açıkçası bir hayli kod yazmamız gerekiyordu. İşte tam bu noktada dilin yapısına C# 2.0 ile birlikte Yeni Bir İterasyon tekniği olan (yield) eklendi. Yine bu yapı IEnumerable ve IEnumerator arayüzleri ile işbirliği yapıyor ama biz programcıların yield sayesinde bu arayüzlerle ilgilenmemiz gerekmiyor.

C# 2.0 ile birlikte yield return ve yield break anahtar sözcükleri eklendi. Bu anahtar sözcükleri geriye IEnumerator ya da IEnumerator<T> döndüren metotlar için geçerlidir.

yield return belli bir sıra ile yapılırsa yapıldığı sıraya göre koleksiyon kümesi oluşturur. Buradaki önemli nokta kümenin IEnumerator türünden olması gerekliliğidir. Buda foreach yapısı ile çalışabilmesi anlamına geliyor. Yani kısa bir örnek ile bunu açıklayalım;

return ile yield return birbirine karıştırılmamalıdır. yield return metodun sonlanması ve geriye bir şey dönmesi anlamına gelmiyor.

yield break ile koleksiyon oluşturduğumuz döngü içerisinde belirli bir koşul altında koleksiyon kümesini sonlandırmak istersek bunu kullanırız. GetMyStringList() metoduna for sayacımız 5 olduğunda koleksiyon kümesini sonlandır ile tekrar düzenlersek;

yield return anahtar sözcüğünün iterasyonu nasıl yaptığını yani arka planda neler oluyoru öğrenmek için 🙂 .Net ile birlikte gelen ILDASM (Intermadiate Language Disassembler) aracı ile inceleyelim.

ILDASM aracını açmak için uygulanacak adımlar

  • Visual Studio Command Prompt açıp ( kendi bilgisayarınızdaki visual studio) açılan ekrana ildasm yazıyoruz
  • Ildasm aracı açıldıktan sonra File menüsünden Open tıklıyoruz ve projenizin dll dosyasını (assembly) veriyoruz.

Karşımıza aşağıdaki gibi bir ekran gelecek

Yukarıdaki örneğe dikkat edersek GetMyStringList() metodunda MoveNext, Reset, Current gibi metot ve özellikleri görüyoruz. Yani compiler yield anahtar sözcüğünü gördüğü yere aslında bizim daha önce uyguladığımız iterasyon tekniği yapıyor ve yield bizim yerimize IEnumerable ve IEnumerator arayüzleri ile işbirliği yapıyor. Aslında compiler arka planda ne kadar mükemmel bir işlem yaptığını görebiliyoruz.

Bu yazımda Yeni Bir İterasyon tekniği olan (yield) hakkında edindiğim bilgileri paylaşmaya çalıştım. Umarım faydalı olmuştur 🙂

Bir sonraki yazımda görüşmek üzere 🙂

Kaynaklar:

Her Yönüyle C# 7.0, Sefer Algan, Pusula Yayincilik

https://docs.microsoft.com/tr-tr/dotnet/csharp/language-reference/keywords/yield

C# Generic Collections

Merhaba arkadaşlar,

Bu yazımda Şablon Tipli Koleksiyon Nesneleri (Generics) hakkında bahsedip her bir koleksiyon nesnesinin bize sunduğu çeşitli özelliklerini inceleyeceğiz. Klasik tipli koleksiyon nesnelerini kullanarak grup nesnelerimizi yöneterek her bir klasik tipli koleksiyon nesnelerini çalışma prensiplerine göre ele almaya çalıştık. Ancak klasik tipli koleksiyon nesneleri object veri tipini kullandıkları için bu hem performans kaybına yaşanıyordu hem de tür güvenliğini sağlanamıyordu. Buna çözüm olarak System.Collection.Generic isim alanında her bir klasik tipli koleksiyon sınıfının şablon tipli versiyonu geliştirilmiştir.

System.Collection.Generic isim alanına genel bakış

C# 2.0 ile birlikte eklenen yeni şablon tipli özelliği sayesinde klasik tipli koleksiyon nesnelerin kullanılması önerilmiyor. Biz de klasik tipli koleksiyon nesnelerini işin mutfağında neler dönüyor ele almıştık. 🙂 System.Collection isim alanında bulunan arayüz ve koleksiyon tabanlı sınıflar ile ilgili serime buradan ulaşabilirsiniz.

Şablon tipli yeni koleksiyonların kullanımı ve amaçları klasik koleksiyonlarla aynıdır. Tek farkları saklanacak veri tiplerinin tek olması ve Koleksiyon yaratıldığı anda belirlenmesi.

List<T> Class

List<T> koleksiyonu ArrayList koleksiyonun karşılığıdır. List koleksiyondaki her bir elemana sıfır tabanlı indeks ile erişe bilmemize olanak sağlayan sınıftır. Hemen hemen birçok özelliği aynıdır. C# ArrayList Class yazıma buradan ulaşabilirsiniz.

List<T> sınıfının diğer metot ve özelliklerine buradan daha detaylı bir şekilde ulaşabilirsiniz.

Dictionary<TKey, TValue> Class

Dictionary<TKey, TValue> koleksiyonu Hashtable koleksiyonunun karşılığıdır. Dictionary anahtar-değer ikilisine sahip koleksiyon tabanlı bir sınıftır. Hemen hemen bir çok özelliği aynıdır. C# Hashtable Class yazıma buradan ulaşabilirsiniz.

Dictionary<TKey, TValue> sınıfının diğer metot ve özelliklerine buradan daha detaylı bir şekilde ulaşabilirsiniz.

SortedDictionary<TKey, TValue> Class

SortedDictionary<TKey, TValue> koleksiyonu SortedList koleksiyonunun karşılığıdır. Bu sınıf hem ArrayList hem de Hashtable sınıflarının karışımı gibidir. Hemen hemen bir çok özelliği aynıdır. C# SortedList Class yazıma buradan ulaşabilirsiniz.

SortedDictionary<TKey, TValue> sınıfının diğer metot ve özelliklerine buradan daha detaylı bir şekilde ulaşabilirsiniz.

IEnumerable<T> ve IEnumerator<T> Intefaces

IEnumerable<T> ve IEnumerator<T> arayüzleri klasik versiyonlarından (IEnumerable, IEnumerator) türetilmiştir. IEnumerable foreach yapısı için uyguladığımız bir arayüz, IEnumerator arayüzü ise listedeki her bir elemana erişmek ve diğer işlemleri yapmak için uyguladığımız arayüzdü. Hatırlamak için C# SortedList Class yazıma buradan ulaşabilirsiniz.

Şablon türlü koleksiyonlar için arayüz niteliğindedir. Kendi koleksiyon sınıflarımızı geliştirirken artık bu arayüzü uygulamamız gerekiyor. Yazımın başında şablon tipli koleksiyonlar dile eklendikten sonra klasik koleksiyon sınıflarının kullanılması önerilmiyor.

Eski arayüzler hayatlarına devam edeceklerdir. Buda geriye dönük uyumluluk içindir.

String değerleri barındıran basit bir koleksiyon sınıfı tasarlayacağız. Bu sınıfa şablon tipli IEnumerable<string> arayüzünü uygulayıp ve IEnumerator<string> arayüzünü bildireceğiz.

IEnumerable<T> sınıfının diğer metot ve özelliklerine buradan daha detaylı bir şekilde ulaşabilirsiniz.

IEnumerator<T> sınıfının diğer metot ve özelliklerine buradan daha detaylı bir şekilde ulaşabilirsiniz.

Queue<T> Class

Queueu<T> koleksiyonu klasik Queue koleksiyonunun karşılığıdır. Queue kuyruktur ve art arda oluşan sıralı dizidir. Hemen hemen birçok özelliği aynıdır. C# Queue Class yazıma buradan ulaşabilirsiniz.

Queue koleksiyonu FIFO mantığı ile çalışır. FIFO ise (First in First out) koleksiyona ilk giren eleman ilk çıkar prensibini uygular.