Ana içeriğe atla

DevExpress XPO ile XmlDataSet İşlemleri

Devexpress XPO .Net platformu için geliştirilmiş bir ORM yazılımıdır. ORM yazılımlarının yaygınlığı ve alternatiflerinin çoğalması DevExpress firmasını bu yazılımı ücretsiz yapmaya itmiş ve doğal olarak bu da beraberinde kullanıcı kitlesinin artmasına neden olmuştur.

Devexpress XPO bir çok veritabanına destek vermekle birlikte özellikle küçük uygulamalar için hayati öneme sahip XML formatında verileri saklamanızı ve üzerinde işlemler yapmanızı sağlayan bir özelliğe de sahiptir.

Yani oluşturduğunuz obje yapılarına göre verilerini XML dosyasında tutmaya, yeni veriler oluşturmaya ve mevcut veriler üzerinde değişiklik yapmaya olanak sağlar. Küçük veriler için tasarlandığı için sorgulama süreçleri de çok hızlı çalışır.

Özetle XML dosylarında CRUD işlemlerini sorunsuzca yapmanıza olanak sağlar.

Bu makalemde Devexpress XPO ile XML veri katmanının nasıl oluşturulduğunu veri ekleme, düzenleme, listeleme işlemlerinin nasıl gerçekleştirildiğini örnek üzerinden anlatmaya çalışacağım.

Örneğimize geçmeden önce önemli bir konuyu açıklamakta fayda var: Eğer uygulamanız çok fazla veri yazma işlemleri yapacaksa alternatif teknolojileri örenğin Sqlite kullanmanızı tavsiye ederim. Devexpress'in desteklediği veritabanlarına buradaki listeden ulaşabilirsiniz.

Veri yazma ve düzenleme süreçlerinin çok az ve genelde verileri görüntüleme veya sorgulama işlemleriniz varsa, tablonuzdaki verilerin sayısı 10 bini geçmeyecekse XMLDataSet özelliğini tercih etmenizi öneririm.

Örnek proje olarak basit bir üyelik sistemi tasarlayacağız. Bunun için kullanıcılar, kişiler ve iletişim bilgilerinin tutulduğu tabloları oluşturacak, tabloya veriler yazacak ve tablodan belirli kriterlere göre veri sorgulayacağız. Arayüz tasarlamak bu makalenin konusu olmadığı için sadece arka plan işlemlerini yapacağız.

Örnek projemiz için  console uygulaması oluşturdum ve proje sonundaki kodları github üzerinden de paylaştım. Projenin tamamını görmek isteyenler buradaki linkten projenin tamamına erişebilirler.

Projeyi oluşturduktan sonra Nuget'tan DevExpress.XPO kütüphanesini aşağıdaki resimdeki gibi ekliyoruz.


Not: Örnek proje .net Core ile oluşturduğum için en son sürümü projeye ekleyebiliyorum. Eğer .net Framework tercih edecekseniz buna uygun sürümü seçmeniz gerekiyor.

İkinci adımda tablolarımızı tasarlamak için sınıfları oluşturacağız.
Genel olarak ORM yazılımları ile çalışırken bir base class oluşturulur ve tüm tablolar bu tablodan türetilmiş olur. Böylece tüm tablolardaki benzer alanlar sabit bir yapıya dönüştürülmüş olur. Biz de örneğimizi bu base objeyi oluşturarak başlıyoruz.

using DevExpress.Xpo;
using System;

namespace DevExpressXpo.XmlDataSetEgitim
{
    [NonPersistent]
    public abstract class BaseObject : XPCustomObject
    {
        public BaseObject(Session session) : base(session)
        {
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
            CreatedTime = DateTime.Now;
            GUID = Guid.NewGuid().ToString();
        }

        [Key]
        [Persistent("GUID")]
        public string GUID { get; set; }

        [Persistent("CREATED_TIME")]
        public DateTime CreatedTime { get; set; }
    }
}

BasObject sınıfımız abstract bir classdır ve bundan sonra oluşturacağımız tüm tablo sınıfları bu sınıftan türetilerek oluşturulacak. Dikkat ederseniz bu BaseObject sınıfı da XPCustomObject sınıfından türetilmiştir ve bu sınıf da "OptimisticLockField" alanı otomatik olarak eklenecektir.

BaseObject sınıfını tanımlarken bir kaç Devexpress Xpo'ya özgü Attribute tanımladık. Bunları da sırasıyla açıklayacak olursak:

NonPersitent Attribute bir XPO tablosu tasarlarken tablonun kalıcı olmayacağını, yani bu isimde tablo oluşturulmayacağını belirtmek için kullanılır. DevExpress XPO'da NonPersitent Attribute "best practice" kullanım olarak da tüm tabloların türeyeceği base sınıfı tanımlamak için kullanılır.

Key Attribute Bir özelliğin anahtar nitelik olacağını belirtmek için kullanılır. XML veri seti ile çalışırken otomatik id üreten bir sequence yapısı olmadığı için "best practice" olarak GUID üretilerek anahtar olarak kullanılır.
Not: XML veri seti de olsa Devexpress XPO tüm tablolar için bir anahtar seçmeği zorunlu kılar. Uygulama içinde bu anahtarı yönetmek bir çok durumda sorun yaratacağı için genelde bu şekilde anahtar üretme mekanizması kullanılır.

Persistent Attribute bir tablonun veya kolunun ismini belirtmek için kullanılır. XML veri setinde bunlar oluşturulacak olan tagların tanımlamasıdır. Genellikle alfa-numerik ve mümkün olduğu kadar Türkçe karakter kullanmadan tasarlama yapmanızı öneririm.

Size Attribute: Sql tabloları tasarlarken varchar tanımlamasının karşılığıdır. Eğer tanımlama yapmazsanız varsayılan değeri 100 olarak atanır ve bu bir çok durumda başınızı ağrıtabilir. Bu yüzden string kolonlar tasarlarken mutlaka Size Attribute'yi tanımlamaya özen gösterin.

Devexpress XPO'nun sahip olduğu diğer Attribute'ları kendi sayfasını ziyaret ederek araştıra bilirsiniz. Ama genel olarak kullanılanlar NonPersitent, Key, Persistent ve Size özelliklerini doğru şekilde kullanmak tablo tasarımı için çok önemli konudur.

Tablo tasarımı ile ilgili bu bilgilerden sonra sırayla tablolarımızı tasarlayabiliriz. İlk olarak People tablosunu tasarlayalım. Dikkat ederseniz tasarlayacağımız sınıf Person, Persistent attribute ile ismini tablo ismini belirtirken PEOPLE olarak tanımlıyoruz.
Kullanıcı sınıfını tanımlarken kullanıcı ve kişi tabloları arasında birebir ilişkinin de kurulduğunu göreceksiniz. Yani ilişkiler nesneler arasındaki ilişkileri kurmakla ilgilidir. Aynı zamanda bir kişinin birden fazla iletişim bilgisi olacağı için iletişim bilgisi ve kişi arasındaki ilişkiyi de 1-N ilişki olarak tasarlıyoruz. Eğer N-N ilişki olursa bu zaman da iki sınıfı bir araya getiren yeni sınıf oluşturmamız gerekecekti

Kişi Sınıfı:
using DevExpress.Xpo;

namespace DevExpressXpo.XmlDataSetEgitim
{
    [Persistent("PEOPLE")]
    public class Person : BaseObject
    {
        public Person(Session session) : base(session)
        {
        }

        [Size(255)]
        [Persistent("NAME")]
        public string Name { get; set; }

        [Size(255)]
        [Persistent("SURNAME")]
        public string Surname { get; set; }
    }
}

Kullanıcı Sınıfı:
using DevExpress.Xpo;

namespace DevExpressXpo.XmlDataSetEgitim
{
    [Persistent("USERS")]
    public class User : BaseObject
    {
        public User(Session session) : base(session)
        {
        }

        [Size(40)] // Size özellik belirtilmezse varsayılan olarak 100 yazılır. Bu durumda 100 karakterden fazla olan veriler için hata alırsınız.
        [Persistent("USERNAME")]
        public string Username { get; set; }

        [Size(1000)]
        [Persistent("PASSWORD")]
        public string Password { get; set; }

        [Persistent("PERSON_GUID")]
        public Person Person { get; set; }
    }
}

İletişim Bilgileri Sınıfı
using DevExpress.Xpo;
using System;
using System.Collections.Generic;
using System.Text;

namespace DevExpressXpo.XmlDataSetEgitim
{
    [Persistent("COMMUNICATIONS")]
    public class Communication : BaseObject
    {
        public Communication(Session session) : base(session)
        {
        }

        [Persistent("COMMUNICATION_TYPE")]
        public ECommunicationType CommunicationType { get; set; }

        [Size(255)]
        [Persistent("VALUE")]
        public string Value { get; set; }

        [Persistent("IS_ACTIVE")]
        public bool IsActive { get; set; }

        [Persistent("PERSON_GUID")]
        public Person Person { get; set; }
    }
}

ECommunicationType Enumu:
namespace DevExpressXpo.XmlDataSetEgitim
{
    public enum ECommunicationType
    {
        Email = 1,
        MobileNumber = 2,
        HomePhoneNumber = 3,
        Fax = 4
    }
}

Sınıflarımızı ve doğal olarak tablolarımızı da oluşturduk. Daha doğrusu XPO gerçek XML verisini siz tabloları kullanmaya başladığınızda oluşturur. Yani nesne tasarlar ve kullanmazsanız sadece bir class olarak kalmaya devam eder.

Tabloları tasarladıktan sonra ikinci aşama verileri işlemeye başladığımız XmlDataSetManager sınıfıdır. Bu sınıfı verileri sorgulamak, yeni  veriler oluşturmak, güncellemek ve silme işlemlerinden önce XML veritabanını yağa kaldıran temel sınıfıdır.

XmlDataSetManager sınıfı
using DevExpress.Xpo;
using DevExpress.Xpo.DB;
using DevExpress.Xpo.Metadata;
using System;
using System.IO;
using System.Linq;
using System.Reflection;

namespace DevExpressXpo.XmlDataSetEgitim
{
    public class XmlDataSetManager : Singleton<XmlDataSetManager>
    {
        private readonly object LockObject = new object();
        private XmlDataSetManager()
        {
        }

        public void Init()
        {
            SetDataLayer();
        }

        public Session GetNewSession()
        {
            var session = new Session(DataLayer);
            return session;
        }

        private volatile IDataLayer _fDataLayer;

        private IDataLayer DataLayer
        {
            get
            {
                SetDataLayer();

                return _fDataLayer;
            }
        }

        public XPClassInfo GetClassInfo(Type t)
        {
            return DataLayer.Dictionary.GetClassInfo(t);
        }

        private void SetDataLayer()
        {
            if (_fDataLayer == null)
            {
                lock (LockObject)
                {
                    if (_fDataLayer == null)
                    {
                        _fDataLayer = GetDataLayer();
                    }
                }
            }
        }

        public void SetDataLayer(IDataLayer dataLayer)
        {
            _fDataLayer = dataLayer;
        }

        private IDataLayer GetDataLayer()
        {
            IDataLayer dl = null;
            XPDictionary dict = new ReflectionDictionary();
            string connectionPoolString = XpoDefault.GetConnectionPoolString(String.Format(@"XpoProvider=XmlDataSet;Data Source={0}\datasource.xml", Directory.GetCurrentDirectory()));
            IDataStore store = XpoDefault.GetConnectionProvider(connectionPoolString, AutoCreateOption.DatabaseAndSchema);
            dict.GetDataStoreSchema(typeof(BaseObject).Assembly);
            dl = new ThreadSafeDataLayer(dict, store);
            Session newSession = new Session(dl);
            XpoDefault.Session = null;
            Assembly executingAssembly = Assembly.GetExecutingAssembly();
            Type[] array = executingAssembly.GetTypes().Where(t => t.IsSubclassOf(typeof(BaseObject))).ToArray();
            newSession.UpdateSchema(array);
            return dl;
        }
    }
}

XML veritabanı altapısını XmlDataSetManager sınıfı ile tanımladıktan sonra artık kişi, kullanıcı ve iletişim bilgileri oluşturma süreçlerine geçebiliriz. Klasik örnek de olsa web siteleri için uyelikte alınan temel bilgilere göre kişi, kullanıcı ve iletişim bilgisi verilerini oluşturacak kodları yazalım.

PersonManager Sınıfı
using DevExpress.Xpo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DevExpressXpo.XmlDataSetEgitim
{
    public class PersonManager : Singleton<PersonManager>
    {
        private PersonManager() { }

        public Person Create(Session session, string name, string surname)
        {
            var person = new Person(session)
            {
                Name = name,
                Surname = surname
            };
            person.Save();

            return person;
        }

        public List<Person> List(Session session)
        {
            return session.Query<Person>().ToList();
        }
    }
}


UserManager Sınıfı
using DevExpress.Xpo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DevExpressXpo.XmlDataSetEgitim
{
    public class UserManager : Singleton<UserManager>
    {
        private UserManager()
        {
        }

        public User Create(Session session, Person person, string username, string password)
        {
            var user = new User(session)
            {
                Person = person,
                Password = password,
                Username = username
            };
            user.Save();
            return user;
        }

        public List<User> List(Session session)
        {
            return session.Query<User>().ToList();
        }
    }
}

CommunicationManager Sınıfı
using DevExpress.Xpo;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DevExpressXpo.XmlDataSetEgitim
{
    public class CommunicationManager : Singleton<CommunicationManager>
    {
        private CommunicationManager() { }

        public Communication Create(Session session, Person person, ECommunicationType type, string value)
        {
            var communication = new Communication(session)
            {
                CommunicationType = type,
                Value = value,
                IsActive = true,
                Person = person
            };
            communication.Save();

            return communication;
        }

        public List<Communication> Get(Session session, string personGuid)
        {
            return session.Query<Communication>().Where(t => t.Person.GUID == personGuid).ToList();
        }
    }
}

Temel sınıflar yazdıktan sonra artık üyelik sınıfını yazabilir ve buradan yeni üye kaydını yapabiliriz.

SignUpManager Sınıfı
using DevExpress.Xpo;
using System;
using System.Collections.Generic;
using System.Text;

namespace DevExpressXpo.XmlDataSetEgitim
{
    public class SignUpManager : Singleton<SignUpManager>
    {
        private SignUpManager() { }

        public bool SignUp(string username, string password, string name, string surname, string email)
        {
            try
            {
                using (Session session = XmlDataSetManager.Instance.GetNewSession())
                {
                    session.BeginTransaction();
                    var person = PersonManager.Instance.Create(session, name, surname);
                    var user = UserManager.Instance.Create(session, person, username, password);
                    var communication = CommunicationManager.Instance.Create(session, person, ECommunicationType.Email, email);
                    session.CommitTransaction();
                }
                return true;
            }
            catch (Exception)
            {
                //Log Exception
                return false;
            }
        }
    }
}

Not: Yukarıdaki örneklerde de gördüğünüz gibi sorgulama işlemlerini Linq To Sql kullanarak yapıyoruz. Linq To Sql ayrı bir konu olduğu için burada bu konuya girmiyorum. Ayrıca MoreLinq de kullanarak sorgularınızın kalitesini daha da artırabilirsiniz.

Farkında değilsiniz belki ama Devexpress XPO kullanarak bir XML veritabanı oluşturdunuz. Tablo oluşturmayı ve tablolara veri yazıp sorgulamayı da yapabilir durumdasınız. Tek eksik kalan örnek kullanımdı. Onu da aşağıdaki kod parçasında yeni bir üyelik yaparak konumuzu tamamlıyoruz.

using DevExpress.Xpo;
using System;

namespace DevExpressXpo.XmlDataSetEgitim
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlDataSetManager.Instance.Init();

            Console.WriteLine("XmlDataSet initialized");

            //SignUpManager.Instance.SignUp("agha_alizade", "123123", "Agha", "Alizade", "agha_alizade@outlook.com");
            using (Session session = XmlDataSetManager.Instance.GetNewSession())
            {
                var communications = CommunicationManager.Instance.Get(session, "1ad116b3-93b0-4d72-a3ad-38185ab4b10a");
            }
            Console.ReadLine();

        }
    }
}

Sorularınız olursa yorumlar kısmından bana yazabilirsiniz.
Makalenin eksik kaldığını düşündüğünüz noktaları varsa bana yazabilirsiniz.

Yorumlar

Bu blogdaki popüler yayınlar

Azərbaycan Dilində Vurğu Qəbul Etmeyen Şekilçiler

Sözlərdə hecalardan birinin digərlərinə nisbətən daha qüvvətli deyilməsinə heca vurğusu deyilir. Üzərinə vurğu düşən hecaya isə vurğulu heca deyilir. Azərbaycan dilində vurğu adətən söz sonuna düşür. Söz şəkilçi qəbul ederkən vurğu adətən şəkilçinin üzərinə keçir. Məsələn: çiç ə k - çiçəkl ə r - çiçəklərd ə n məkt ə b - məktəbl i - məktəblil ə r - məktəblilərd ə n Buna baxmayaraq dilimizdə bir sıra şəkilçilər var ki onlar vurğu qebul etmirlər. Bu məqalədə Azərbaycan dilində vurğu qebul etməyən şəkilçilər incələnəcək ve bu şekilçilərin hansı hallarda vurğu qebul edib hansı hallarda vurğu qebul etmediyi araşdırılacaqdır. Eyni zamanda bildirmək istəyirəm ki vurğu ilə bağlı daha geniş və ətraflı məlumat üçün Azərbaycan Dilində Vurğunun Praktik Məsələləri adlı məqaləyə də nəzər yetirə bilərsiniz.  1. İsimlərdəki şəxs(xəbərlik) şəkilçiləri Məsələn: müəli'məm müəli'msən müəli'mdir müəli'mik müəli'msiniz müəli'mdirlər Qeyd: -dır4

Ağaçlar Kireçle veya Badana İle Neden Boyanır?

Ağaçlar kireçle boyanmasının veya badana yapılmasının hem çevreye hem de doğaya, ağaçlara faydası var. Bu makalede bu geleneği enine boyuna tartışmaya çalıştık. Ağaca zarar veren mikrop ve bakterileri öldürür. Ağacı çok aşarı soğuk havalarda ve çok aşırı sıcak havalarda korur. Ağacın çürümesini ve kurtlanmasını önler. Ağacın gövdesinin alabileceği zararları en az düzeyde düşürmeyi sağlar. Hoş, güzel, hijyenik, temiz pırıl pırıl bir görüntü oluşturur. Ayrıca çok sıcak havalarda da ağacı yanmaya karşı korumak. En büyük etkisi soğuk havalarda ağacı don vurmalarına karşı korumak . Küresel ısınma göz önüne alındığında mevsim değişiklikleri ani don, ani ısı artışları ve azalışları sonucunun doğuracağı etkenler için yararlı etkin bir yöntem. Gövdeden obur dalların çıkmasını azaltmak için sürülür. Kireçleme ağaçları güneş yanığından korumak için yapılıyor. Ağaçlar da güneşten yanabiliyorlar. Bu arada odun dokudaki gözenekleri doldurarak kapattığı için, zararlıların yuv

Medyan (Ortanca) Nedir? Nasıl Hesaplanır? Nerelerde Kullanılır?

Medyan işlemi olasılık hesaplamalarında sıkça kullanılan bir sayı dizisinin ortalamasını hesaplamak için alternatif yöntemlerden bir tanesidir. Ortanca medyan işleminin diğer adıdır. Matematiksel olarak medyan işlemi bir sayı dizisi küçükten büyüğe sıralayarak ortada kalan elemanı medyan değeri olarak belirleme işlemidir. Örnek verecek olursak: 2, 1, 5, 4, 5, 1, 2, 3, 5 serisi sıralanırsa 1, 1, 2, 2, 3, 4, 5, 5, 5 serisi elde edilir. Bu seri 9 elemanlı olduğundan ortadaki, yani 5. eleman (medyan) olacaktır. 5. eleman 3 sayısıdır. Yani ortanca değeri 3'dür Eleman sayısı tek sayı olan bir seride medyan değerin sırasının hesaplaması şu şekilde formüle edilir. Medyanın Sırası = (Eleman Sayısı + 1) / 2 Bu formülü yukarıdaki örneği uygulayacak olursak; Medyanın Sırası = (9 + 1) / 2 = 5 Veri serisi eleman sayısı bir çift sayı ise bu durumda serinin 2 medyanı olacaktır. Örneğin 2, 1, 5, 4, 5, 1, 2, 3, 5, 4 serisi sıralandığında 1, 1, 2, 2, 3, 4, 4, 5, 5, 5 s