Makale Özeti

Gerçek bir mobil uygulama sunucuya sürekli bir bağlantı olmadığı durumda da çalışabilme imkanı vermelidir. Bunu sağlayabilmek için ise bağlantı olmadığı durumları da düşenerek, tasarımınızı ona göre yapmalısınız.

Makale


Mobil Uygulamalarda DataSet ve XML Kullanımı

Gerçek bir mobil uygulama sunucuya sürekli bir bağlantı olmadığı durumda da çalışabilme imkanı vermelidir. Bunu sağlayabilmek için ise bağlantı olmadığı durumları da düşenerek, tasarımınızı ona göre yapmalısınız. Bu noktada .NET Compact Framework uygulama geliştiricilere adeta bir ilaç gibi ortaya çıkmakta, uygulama geliştirimini kolaylaştırmakta ve zevkli bir hale getirmektedir.

Diğer uygulama türlerinden de bildiğimiz gibi ADO.NET çeşitli veri kaynaklarına erişime izin vermektedir. SQL Server, SQL Server CE, OLE DB aracılığıyla birçok veri kaynağı ve XML verileri … Veri erişiminde uzaktaki bir veri kaynağına bağlanmak ile yereldekine bağlanmak arasında fark yoktur.

ADO.NET, uygulama geliştiricilere bağlantısız durumlarda dahi verilerle çalışabilme imkanı vermektedir. Bunu sağlayabilmek için ise “DataSet”ten yararlanmaktayız. DataSet, bir veya birçok tabloyu barındıran sanal bir veritabanı olarak bellekte yer alır. Datasetin tablolarındaki veriler uygulama çalışırken kullanıcı tarafından değiştirilebilir, silinebilir ve yenileri girilebilir. Dataset, uzaktaki bir veritabanından, yereldeki SQL Server CE veritabanından verileri çekerek ya da uygulama içerisinden kod ile oluşturulabilir. Dataset içerisinde birden fazla tablo olması durumunda bu tablolar arasında ilişkiler de DataSet nesnesi içerisinde tutulur.

ADO.NET, DataSet ve diğer bileşenler arasında veri alışverişini sağlamak için XML’i kullanır. Ayrıca uygulama sonlandırıldığında ya da mobil cihaz kapatıldığında verilerin kaybolmasını engellemek için veriler cihaz üzerinde bir XML dosyasında saklanabilir.

Yereldeki veya uzaktaki bir veritabanındaki verilere ulaşabilmek için kullanabileceğimiz nesneler diğer uygulama türlerinde kullandıklarımızla aynıdır. Yine Connection, Command, DataReader ve DataAdapter nesnelerinden yararlanırız. Bunların neler olduğunu açıklamaya sanırım gerek yoktur.

Uygulamaların sunucuya bağlantı olmadığı durumlarda da sanki sürekli bir veritabanı bağlantısı varmış gibi çalışabilmesini sağlayan nesnenin DataSet olduğunu söylemiştik. Şimdi bunun nasıl sağlandığını inceleyelim.

Bir DataSet, tipli ya da tipsiz (typed, untyped) olabilir. (Bazı terimlerin tam Türkçe karşılıklarını bulmak zor olabiliyor) Tipli ve tipsiz arasındaki fark tipli datasetin XML schema bilgisi içeriyor olmasıdır. Tipsiz bir datasette XML schema yoktur ve genelde verileri geçici olarak mobil uygulama içerisinde tutmak için kullanılır. Tipsiz bir datasetin belirli bir yapısı olmadığı için tablolar, sütunlar ve kısıtlar (constraint) uygulama içerisinde kodla oluşturulmalıdır.

Bir dataset bir veya birçok tablo ve bu tablolar arasındaki ilişkilerden oluşur. Tablo, uygulama içerisinde kullanılacak verileri tutar. Bir tablo sütun, satır ve kısıtlardan oluşmaktadır. Örneğin bir UniqueConstraint ile bir sütundaki tüm verilerin birbirinden farklı olması sağlanabilir.

Tablolar arasında ilişkiler olabilir demiştik. Bunu sağlayan ise DataRelation’dir. DataRelation, bir tablo içerisindeki verileri başka bir tablo ile ilişkilendirir, bağlar. Tablolar arasındaki ilişkileri tutar ve belirtilen kısıtların kontrol edilmesini sağlar.

Uygulama içerisinden kod ile dataset ve onun içinde bulunacak tabloları oluşturabilirsiniz. Örneğin:

DataSet ds = new DataSet (“Veriler”);
ds.Tables.Add(“tablo”);
ds.Tables[“tablo”].Columns.Add(“Ad”, System.Type.GetType(“System.String”));
ds.Tables[“tablo”].Columns.Add(“Soyad”, System.Type.GetType(“System.String”));

İlk satırda “Veriler” adında bir tipsiz DataSet oluşturuyoruz. İkinci satırda “tablo” adında bir DataTable yaratıyoruz. Üçüncü ve dördüncü satırlarda Add metodunu kullanarak tablomuza “Ad” ve “Soyad” sütunlarını ekliyoruz ve bu sütunlara string değerler girilebileceğini belirtiyoruz.

Yukarıdaki örnekte sütunların alabilecekleri değerler string olarak genel bir veri tipi ile belirtilmiştir fakat bir sütunun alabileceği değerler diğer sütunlardaki (aynı satırda olmak şartıyla) değerlere bağlı olarak da belirlenebilir. Bir sütundaki sahalara değer girilmemesi durumunda geçerli olacak default değer de belirtilebilir. Örneğin:

DataTable Dt = new DataTable();
Dt.Columns.Add(“firinMarkasi”, System.Type.GetType(“System.String”));
Dt.Columns[“firinMarkasi”].DefaultValue = ”TEBA”;
Dt.Columns.Add(“firinFiyat”, System.Type.GetType(“System.Decimal”));
Dt.Columns.Add(“firinFiyatKDVli”, System.Type.GetType(“System.Decimal”), “firinFiyat * 1.18”);

Yukarıdaki tablonun “firinMarkasi” sütununa girilen her veririn farklı olmasını (unique) ise aşağıdaki gibi bir kısıt (constraint) tanımlayarak sağlayabiliriz :

UniqueConstraint kisitlama = new
UniqueConstraint(“firinID”, Dt.Columns[“firinMarkasi”]);
Dt.Constraints.Add(kisitlama);

Bir tablonun nasıl oluşturulacağını ve kısıtların nasıl ekleneceğini öğrendik, şimdi sıra tablomuza kod ile verilerin nasıl girileceğini öğrenmeye geldi:

DataRow Satir = ds.Tables[“tablo”].NewRow();
Satir[“Ad”] = “Tarık”;
Satir[“Soyad”] = “Özkan”;
ds.Tables[“Tablo“].Rows.Add(Satir);

Bir DataRow’daki verileri okurken veya yazarken sütunun adını ya da kaçıncı sütun olduğu bilgisini kullanabiliriz. Örneğin bir row’daki “Soyad“ bilgisini aşağıdaki gibi iki farkli şekilde girebiliriz:

Satir[“Soyad“] = “ÖZKAN“;
Satir[2] = “ÖZKAN“;

Tabloya verileri bu şekilde girmek zorunda değiliz, bir SQL Server ya da SQL Server CE veritabanından verileri sorgu ile çekip daha basit bir şekilde girebiliriz ya da verileri bir XML dosyasından da okutturabiliriz. Verileri hangi veri kaynağından almış olursak olalım tablodaki veriler üzerinde bir değişiklik yaptığımız zaman orijinal veriler hemen değiştirilmez. Yeni ve orijinal hallerinin her ikisi de tutulur. Her satırın (row) RowState adında bir özelliği vardır ve hangi satırın eklendiği, silindiği, değiştirildiği ya da değiştirilmediği bilgisini tutar.

Orijinal veriler üzerinde yapılan değişikliklerin kalıcı olmasını sağlamak, eskileri silmek için yapılması gereken AcceptChanges metodunu çağırmaktır. Benzer şekilde RejectChanges metodu ile yapılan değişikliklerin göz ardı edilmesi de sağlanabilir.

Dataset’e bellekteki veritabanı diyebiliriz. Cihaz açık olduğu sürece veriler korunacak, cihazın şarjı bittiğinde veriler yok olacaktır. Dataset içersindeki verilerin cihaz kapatıldığında kaybolmamasını istiyorsak verileri bir veritabanına ya da bir XML dosyasına yazmalıyız.

Dataset’in WriteXml metodu XML verilerinin dosyaya yazılmasını sağlar. Bunu sağlamak için ise metodun ilk parametresinde dosya adını belirtmek yeterlidir. WriteXml metodu normalde Xml Schema bilgisi içermez. Xml Schema bilgisinin de olması istenirse ikinci bir parametre ile belirtilmelidir. Bu parametrenin alabileceği değerler ise şunlardır: IgnoreSchema (default değerdir ve Dataset içeriğini Xml Schema olmaksızın kaydeder), WriteSchema (veri ile birlikte schema bilgisi olacağını belirtir) ve DiffGram. DiffGram, DataSet nesnesinin özel bir XML formatında kaydedilmesini sağlar. DiffGram, DataSet nesnesinin o anki durumunun korunmasını sağlar, yani satırların hem orijinal hallerini hem de o anki hallerini yazar.

Aşağıdaki kod dataset içerisindeki verilerin Veriler.xml adlı dosyaya nasıl yazılacağını göstermektedir.

System.IO.FileStream myFileStream = new System.IO.FileStream("windows\\Veriler.xml", System.IO.FileMode.Create);
System.Xml.XmlTextWriter myXmlWriter = new System.Xml.XmlTextWriter(myFileStream, System.Text.Encoding.Unicode);
myDataset.WriteXml(myXmlWriter, XmlWriteMode.WriteSchema);
myXmlWriter.Close();

Yukarıda dört satır kodu yazmak istemiyorsanız aynı işi tek satırda şu şekilde halledebilirsiniz:

myDataset.WriteXml(“windows\\Veriler.xml”);

ReadXml metodu ise DataSet’i doldurmak için kullanılır. İlk parametre veri kaynağını belirtir ve zorunludur, ikinci parametre ise okuma modunu belirtir ve zorunlu değildir.

DataSet içerisindeki verilerin hem orijinal hallerinin hem de o anki hallerinin cihaz kapandıktan sonra kaybolmamasını istiyorsak dosyaya yazdırırken DiffGram parametresini kullanıyorduk, yine benzer şekilde kaydettiğimiz verilerin dosyadan DataSet içerisine aktarılmasını sağlamak için de ReadXml metodunun ikinci parametresini DiffGram olarak kullanırız. İkinci parametre Auto olarak belirtilirse ReadXml metodu Xml kaynağını inceler ve uygun okuma modunun ne olduğuna karar verir. DiffGram dışındaki parametreler şunlardır: ReadSchema, InferSchema ve IgnoreSchema.

Aşağıdaki örnek kod verilerin Veriler.xml dosyasından dataset içerisine nasıl okunduğunu göstermektedir:

DataSet ds = new DataSet();
System.IO.FileStream myFileStream = new System.IO.FileStream("windows\\Veriler.xml", System.IO.FileMode.Open);
System.Xml.XmlTextReader myXmlReader = new System.Xml.XmlTextReader(myFileStream);
ds.ReadXml(myXmlReader, XmlReadMode.ReadSchema);
myXmlReader.Close();