23 Ağustos 2009

.Net Compact Framework 3.5 – LINQ Uygulamaları – Linq To Dataset

Konu ile ilgili bir önceki yazımızda ifade ettiğimiz üzere .Net Compact Framework 3.5 ile birlikte artık mobil cihaz uygulama geliştiricileri bu platform üzerinde geliştiriyor oldukları uygumalarda “belirli sınırlar” içerisinde LINQ (Language Integrated Query) olarak ifade edilen altyapı ile “doğal yollarla” ellerindeki kaynakları sorgulayabilmektedirler. Bu bağlamda .Net Framework üzerinde LINQ üzerine onlarca farklı provider geliştirilmiş ve halen de geliştirilmeye devam edilmektedir.

Daha önce de ifade ettiğimiz üzere .Net Compact Framework üzerinde LINQ aşağıdaki sınırlar çerçevesinde desteklenmektedir ;

  • Standart Query Operators
  • Linq To Dataset
  • Linq To XML

Bu yazımızda Linq To Dataset tarafındaki altyapıyı inceleyecek, LINQ ile mobil cihaz uygulamaları geliştirirken Dataset, DataTable ve DataRow’ lar üzerinde sorgulama işlemlerinin nasıl gerçekleştirileceğini örneklendireceğiz.

Dataset – DataTable – DataColumn - DataRow

Bilindiği üzere başlıkta yazan temel 4 kavram Ado.Net Disconnected (Bağlantısız) mimarinin temel yapı taşları olmaktadır. Bu noktada hedef herhangi bir x veri kaynağından gelen relational (ilişkisek) verilerin memory üzerinde konumlandırılması, ve verilerin herhangi bir t anında manipule (Add, Delete, Modify) edilmesi ve tekrardan merkezi verikaynağına gönderilmesi ise Ado.Net üzerinde tanımlı olan sınıflar (xxxDataAdapter, xxxDataReader, xxxCommand, xxxConnection v.b.) vasıtasıyla verilerin çekilmesi ve bu verilerin “memory üzerindeki veritabanımız” olarak kabaca ifade edebileceğimiz DataSet’ ler içerisinde oluşturduğumuz DataTable’ lara yüklememiz gerekmektedir.

DataSet genel olarak aşağıdaki hiyeraşri ile oluşturulmaktadır.

Resimden de anlaşılabileceği üzere DataSet provider bağımsız bir veri saklama, yönetme v.b. otamıdır. Siz DataSet’ in verilerini herhangi x bir veri kaynağı üzerinden çekebileceğiniz gibi örneğin bir web servis ya da bir WCF servis çağrısı sonucunda gelen XML üzerinden de yükleyebilmektesiniz. Genel olarak DataSet bir Container görevi görmekte, veriler DataSet içerisindeki DataTable’ lar üzerinde konumlandırılmaktadır. DataTable ise DataColumn (Sütunlar) ve DataRow (Satırlar) koleksiyonlarından oluşmaktadır. Ayrıca bu DataTable ‘ lar arasında DataSet seviyesinde DataRelation (İlişkiler) konumlandırarak ilintili kayıtlar arasında dolaşabilekteyizdolaşabilmekteyiz.

Bu noktaya kadar kısa bir DataSet – DataTable – DataColumn – DataRow kavramları hakkında bilgi sahibi olduk. Sıra geldi yazımızın asıl konusuna.

Normalde şartlarda DataTable üzerindeki bir verinin sorgulanması “çok sınırlı” olarak sınıf üzerindeki Select fonksiyonu ya da bu DataTable üzerinden oluşturulan bir DataView objesinin Filter özelliği vasıtasıyla “belirli sınırlar içerisinde” gerçekleştirilebilmektedir. Bu noktada daha kapsamlı bir sorgulama altyapısının olması, en azından halihazırda kullanıyor olduğumuz sql-tipi sorgulama altyapısının uygulanabilir olması uygulama geliştiricilere ciddi avantajlar kazandıracaktır.

Linq To Dataset bize bu altyapıyı sunmaktadır. .net Compact Framework 3.5 ile birlikte gelen System.Data ve System.Data.DataSetExtensions referanslarının projeye eklenmesinin sonusunda DataTable, DataRow ve DataView sınıfları içerisinde bu sorgulamaya altyapı sağlayacak konu ile ilgili birkaç Linq Extension Method’ u gelmektedir.

IntelliSense üzerinden DataTable’ a baktığımızda ise ;

İki adet çok kritik extension method gelmektedir. AsDataView Extension Method’ u DataTable üzerinden direk DataView oluşturmaya, AsEnumerable extension method’ u ise tablo içerisindeki DataRow’ ların içerisinde bulunduğu “içi dolu” bir EnumerableRowCollection instance’ ı dönmektedir. Mükemmel. Bilindiği üzere LINQ temel anlamda IEnumerable üzerinde konumlandırıldığı düşünülürse bu tip bir kaynağın sorgulanması ciddi anlamda kolaylaşacaktır.



İşte tanıdığımız bir sürü extension method !

Bu noktada birkaç detayı daha netleştirelim. Bilindiği üzere DataSet’ ler “hazırlanışlarına göre” 2 farklı şekilde olabilmektedir ; typed ve untyped.

Typed DataSet’ ler “genellikle” bir code-generator tarafından oluşturulan ve içeriğine “daha hakim olabileceğimiz” cinsten DataSet’ lerdir. Örneğin, DataSet içerisinde 2 adet DataTable oluşturulduğunu varsayalım ; Employees ve Orders. Bu tablolara standart olarak ;

ulaşabilmekteyiz. Typed olan bir DataSet içerisindeki structure, veri kaynağına bakarak hazırlanacağından, yukarıdaki yönteme “alternatif” olarak şu şekilde de ulaşabileceğimiz bir model “code generetor” tarafından oluşturulmaktadır ;



Bu yöntem “eğer uygulanabiliyorsa” ciddi bir avantaj oluşturmakta, DataSet’ in yapısını anlamamıza ve işlem yapmamıza çok daha fazla olanak sağlamaktadır.

Genel olarak Linq To Dataset ile Typed ve UnTyped DataSet’ ler üzerinde sorgulama ya da filtreleme işlemleri gerçekleştirebilmektesiniz.

Gelelim uygulama örneklerine. Örneğimizde hem Typed hem Untyped DataSet’ ler kullanarak Linq To Dataset kod blokları geliştireceğiz. Bu noktada Typed DataSet’ i Northwind’ in Sql Server Compact Edition için hazırlanmış örnek veritabanı üzerinden “otomatik” olarak oluşturacağız.

Projemize bu örnek veritabanını ;

Patikası üzerinden ekliyoruz ; ve ekrana gelen Typed Dataset oluşturma sihirbazından Orders ve Employees Tablolarını seçiyoruz. İşlem sonucunda aşağıdaki şemaya sahip bir DataSet’ in projemiz içerisinde oluşturulmuş olması gerekmektedir.

Ayrıca, verilerin doldurulabilmesi adına her DataTable ile ilişkili TableAdapter’ ler ise otomatik olarak eklenmiştir.

Sıra geldi bu verileri sorgulamaya. Linq To Dataset içerisinde Standart Query Operators olarak ifade edilen operatörleri kullanabilmektesiniz. Sorgulama hem query expression yöntemiyle hem de extension method’ lar ile gerçekleştirilebilmektedir.

Uygulamamızın yüklenmesiyle birlikte veritabanı üzerinden Employees ve Orders tablolarını dolduruyoruz.

Ve sorgulamaya başlıyoruz. İlk örneğimizde Employees DataTable’ ı içerisinde EmployeeId değeri 5’ ten büyük olan DataRow’ ları seçelim ve Firstname değerlerine göre tersten sıralatalım.


Uygulama çalıştırılıp Button’ a basıldığında ise ;

Yukarıdaki sonuç kümesi elde edilmektedir. Id’ si 5’ ten büyük olan personellerin Firstname’ e göre tersten göre sıralanmış hali.

Bu noktada kod bloğunu biraz açıklamamız gerekmektedir.


Öncelikle dikkat edilirse sorgulama modeli Linq To Dataset’ te en ufak bir farklılık taşımamaktadır. Standart Query Expression modeli ile birebir aynıdır. Bu noktada dikkat çeken 2 adet nokta bulunmaktadır. Bunlardan ilki “r” sembolik adıyla anlık olarak temsil edilen DataRow sınıfı içerisinde normal şartlarda olmayan bir extension method’ un olmasıdır ; Field.

Bu method, aranan kolon değerini, kendisine gönderilen kolon ismi üzerinden arayarak generic parametresine verilen tipte geri döndürmektedir. Bu noktada Employee Id kolon değerini int tipinde kullanıcıya döndürmekte ve incelemeye olanak sağlamaktadır. Süper ! Sorgulama esnasında tam ihtiyaç duyabileceğimiz bir extension method. Bunun dışında bir extension Method daha DataRow üzerinde gelmektedir ; SetField. Bu method ise belirlenen kolon’ a T generic parametresinde belirtilen değer tipiyle gönderilen değeri kaydetmektedir.

Kod bloğunu incelemeye devam ediyoruz. Sorgu sonucunda elimize OrderedEnumerableRowCollection tipinde bir sonuç kümesi dönmektedir. Bu sonuç kümesini bu haliyle Complex DataBinding gerçekleştirebilecek bir kontrole (Örn : DataGrid) DataSource olarak gönderememekteyiz. DataSource’ un IList’ i implemente etmesi gerekmektedir.

Bu noktada hem IList noktasında hem de bir sonraki aşamada filtreleme yapabilmek adına en mantıklı çözüm DataView olmaktadır. Linq To Dataset paketi içerisinde gelen Extension Method AsDataView() ile elimizdeki EnumerableRowCollection topluluğunu tek bir method ile DataView’ a çevirebilmekte, DataSource olarak gönderebilmekteyiz.

Farklı bir örnek üzerinde çalışalım. Bilindiği üzere ilişkili tablolar sql tarafında Join sorguları ile ortaklaşa sorgulanabilmekte, birden fazla tablo üzerinden alınan veriler birleştirilebilmektedir.

Linq To Data üzerinde de join sorguları gerçekleştirebilmektesiniz ! Örneğimizde Orders tablosu ile Employees tablosu arasında Employee Id alanı üzerinden bir ilişki bulunmaktadır.

Hedefimiz ; Orders tablosundan satış bilgilerini almak ve bunun yanında Employee Id yerine bu satış ile ilişkili personelin Ad – Soyad (Firstname + Lastname) bilgilerini almaktır. Her iki tabloyu Load’ ta doldurduktan sonra aşağıdaki sorguyu çalıştırıyoruz :

Bu noktada sonuç kümesinin DataRow’ lardan oluşmamasından ötürü sonuç kümesini DataView’ e dönüştürememekteyiz. Fakat DataGrid IList implemantasyonunu sağlayan List değerlerini gösterebildiğinden Sonuc ‘ u ToList() method’ u ile List e çeviriyoruz. Ve sonucunda aşağıdaki görünümü elde ediyoruz ;

Peki, şu ana kadar tüm bu örnekleri Typed DataSet’ e uygun olarak hazırladık. Ya elimizde structure’ ı hakkında bu şekilde çalışamayacağımız, untyped bir DataSet olsaydı ? Yukarıdaki sorguyu UnTyped DataSet’ e uygun olarak tekrar yazıyoruz ;



Yukarıdaki kod bloğu dikkatlice incelenirse bir önceki kod bloğu ile arasında hem farklar hem de benzerlikler olduğu rahatlıkla anlaşılabilecektir. Gelelim farklılıklara ;

Bir önceki kod bloğunda TypedDataTable olarak DataSet’ in Employees özelliği üzerinden DataTable’ a direk ulaşıyor, join uygulayabiliyorduk. Bu noktada DataTable normalin dışında System.Data.TypedTableBase sınıfından kalıtım aldığından direk olarak join uygulanabilmektedir. (Çünkü bu kalıtım sonucunda DataTable IEnumerable implemente etmektedir). Fakat UnTyped DataTable IEnumerable implemente etmediğinden join operasyonlarına sokulamamaktadır. Bunu aşabilmek adına UnTyped DataTable içerisinde AsEnumerable() adında bir extension method bulunmakta, tablo içerisindeki DataRow’ ları sorgulayabilecek yapıya dönüştürmektedir.

Bunun dışında alanlara direk “özellikler üzerinden” ulaşamamakta (Örn : Employees.Employee_ID), DataRow içerisinde bulunan Field generic extension method’ u ile ulaşılmaktadır. (Örn : en.Field(“Employee Id”)). Kod bloğunu çalıştırdığımızda ise birebir aynı sonucu almaktayız.

İşte bu kadar !

Bütün bunların dışında gelen sorgu sonucu üzerinde diğer extension methodları kullanarak (sum, count v.b.) birçok işlemi gerçekleştirebilmektesiniz.

Bu yazımızda genel olarak Linq To Dataset kavramına değindik. Örnek uygulamayı sisteme aktardıktan sonra buradan yayınlayacağım. Bir başka yazıda görüşmek dileğiyle.

Hiç yorum yok:

Yorum Gönder