Date Image Wednesday, July 27, 2011 | Kategoriler | Asp.Net, C#, LLBLGen Pro, Sql, Tümü

LLBLGen Pro 3.0 Bulk Insert

Projelerde kullanılan orm araçları iş yükünü hafifleterek developerların zaman kazanmasını sağlamaktadır. Günümüzde orm araçlarına bakış açıları değişkenlik gösterebilmektedir. Her şirket, her developer kendince haklı nedenlerden dolayı orm araçlarını kullanır ya da kendi orm kütüphanelerini geliştirebilir. Ancak şöyle bir gerçek var ki o da zamanın önemi çok büyüktür.

Orm konusunda kısaca bir kaç cümle kurduktan sonra konumuza geri dönüyorum. Orm araçlarından LLBLGen Pro ile ilgili küçük bir işlem yapacağız.

Sql Server tarafında kullancağımız database diyagramı aşağıdaki gibidir :

LLBLGenTest DB Diagram

LLBLGen nesnelerinin generate edilmesi işlemlerini burada anlatmayacağım. Gerekirse bunun için ayrı bir yazı hazırlayabilirim. Şimdi basit bir tasarımla bir asp.net web form uygulaması oluşturalım.

LLBLGenTest Page Design

Insert işlemleri için kullanacağımız Helper classları oluşturmak istiyorum. Veritabanı işlemlerini bu helper classlar yardımıyla yapacağız. Bunun için öncelikle BaseHelper adında bir base class oluşturalım ve bir kaç metot ekleyelim.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using LLBLGenTest.EntityClasses;

using LLBLGenTest.CollectionClasses;

using System.Collections;

using SD.LLBLGen.Pro.ORMSupportClasses;

using System.Diagnostics;

 

namespace LLBLGenTest.WebApplication.Helpers

{

    public class BaseHelper

    {

        public void BulkInsert<TEntity>(EntityCollectionBase<TEntity> collection) where TEntity : EntityBase

        {

            Stopwatch timer = new Stopwatch();

            try

            {

                timer.Start();

                collection.SaveMulti(false);

            }

            catch

            {

 

            }

            finally

            {

                timer.Stop();

                LogHelper.Insert(new Log

                                {

                                    Message = string.Format("BulkInsert method executed.{0} ms", timer.ElapsedMilliseconds)

                                });

            }

        }

 

        public void Insert(EntityBase entity)

        {

            Stopwatch timer = new Stopwatch();

            try

            {

                timer.Start();

                entity.Save();

            }

            catch

            {

 

            }

            finally

            {

                timer.Stop();

                LogHelper.Insert(new Log

                {

                    Message = string.Format("Insert method executed.{0} ms", timer.ElapsedMilliseconds)

                });

            }

        }

    }

}

 

Kısaca Helper metotlarımızdan bahsedelim. BulkInsert generic metotu EntityBase nesnesinden türeyen entity sınıflarını taşıyan collection nesnelerini parametre olarak lamaktadır ve LLBLGen e özgü bu collection nesnesinin SaveMulti  metotu çağırılarak bulk insert işlemi yapılır. Bu şekilde sql server üzerinde tek bir bağlantıda collection nesnesi içerisindeki entitylerin tümü insert edilir ve bağlantı kapatılır. Bu metotta işlem sonrasında bir de log tutuyoruz. Burada istenilen ek özellikler eklenebilir, helper classlarımızı istediğimiz gibi genişletebiliriz.

                Şimdi de ContentHelper classımızı oluşturalım. Bu sınıf ContentEntity nesneleri üzerinde işlemler yapacağımız sınıf olacaktır.

using LLBLGenTest.EntityClasses;

using SD.LLBLGen.Pro.ORMSupportClasses;

 

namespace LLBLGenTest.WebApplication.Helpers

{

    public class ContentHelper : BaseHelper

    {

        public EntityBase Get(long id)

        {

            ContentEntity content = new ContentEntity();

            if (content.FetchUsingPK(id))

            {

                return content;

            }

            else

            {

                return new ContentEntity();

            }

        }

    }

}

 

                ContentHelper classımız şuan sadece Get metotunu içermekte ve bu metot Content  long tipinde id parametresi alarak content tablosundan primary key alanı (ID) id parametresine eşit olan content i fetch ederek geriye dönüyor.

Son olarak da CategoryHelper metotumuzu yazalım.

using LLBLGenTest.CollectionClasses;

using LLBLGenTest.EntityClasses;

using SD.LLBLGen.Pro.ORMSupportClasses;

 

namespace LLBLGenTest.WebApplication.Helpers

{

    public class CategoryHelper : BaseHelper

    {

        public EntityCollectionBase<CategoryEntity> Get()

        {

            EntityCollectionBase<CategoryEntity> categories = new CategoryCollection();

            categories.GetMulti(null);

            return categories;

        }

    }

}

                CategoryHelper classımız tüm kayıtlı kategorileri geri dönen metotu içeriyor. Burada CategoryCollection nesnesinin GetMulti metotu bu iş için kullanılıyor ve parametre olarak predicate almakta ancak biz bir kritere göre kategorileri çekmek istemediğimiz için bu parametreyi null geçerek tüm kategorilerin gelmesini sağlıyoruz.

                Helper classlarımızı tamamladığımıza göre sıra basit bir tasarımla oluşturduğumuz sayfamızın code behind kısmını düzenlemeye geldi. Sayfamızın code behind kodları aşağıdaki gibi olacaktır.

using System;

using System.Web.UI.WebControls;

using LLBLGenTest.CollectionClasses;

using LLBLGenTest.EntityClasses;

using LLBLGenTest.WebApplication.Helpers;

 

namespace LLBLGenTest.WebApplication

{

    public partial class _Default : System.Web.UI.Page

    {

        protected void Page_Load(object sender, EventArgs e)

        {

            if (!IsPostBack)

            {

                BindArticle();

                BindCategoryCollection();

            }

        }

 

        private void BindCategoryCollection()

        {

            CategoryHelper categoryHelper = new CategoryHelper();

            CategoryList.DataSource = categoryHelper.Get();

            CategoryList.DataBind();

        }

 

        private void BindArticle()

        {

            ContentHelper contentHelper = new ContentHelper();

            var content = contentHelper.Get(1);

 

            TitleText.Text = content.Fields["Title"].DbValue.ToString();

            ContentText.Text = content.Fields["Text"].DbValue.ToString();

        }

 

        protected void UpdateButton_Click(object sender, EventArgs e)

        {

            ContentHelper contentHelper = new ContentHelper();

            ContentCategoryCollection contentCategoryCollection = new ContentCategoryCollection();

            foreach (ListItem categoryCheck in CategoryList.Items)

            {

                if (categoryCheck.Selected)

                {

                    contentCategoryCollection.Add(new ContentCategoryEntity

                                                    {

                                                        CategoryId = Convert.ToInt64(categoryCheck.Value),

                                                        ContentId = 1

                                                    });

                }

            }

            contentHelper.BulkInsert<ContentCategoryEntity>(contentCategoryCollection);

        }

    }

}

 

                Burada öncelikle örnek olduğu için ID si 1 olan Content i çekerek Title ve Text bilgisini ekrandaki labellara set ediyoruz. Sonrasında ise CategoryList adını verdiğimiz checkboxlist kontrolümüze helper classımızın yardımı ile kategorileri bind ediyoruz.

                Şimdi yazımızın konusunu oluşturan bulk insert işleminin başlatılması için gereken kodları yazacağız. Bunun için UpdateButton adli butonumuza tıkladığımızda seçilen kategorileri ve contentimizi bir ContentCategory koleksiyonuna ekliyoruz.

                BulkInsert işlemini gerçekleştirmek için tek yapmamız gereken şey helper classımızda oluşturduğumuz metotu koleksiyon parametresi ile işletmektir. Bundan sonra koleksiyon nesnemizin SaveMulti metotu çalışacak ve veritabanına content ve category eşleşmelerini ekleyecektir.

                Şimdi sayfamızı çalıştıralım.Ekran görüntüsü aşağıdaki gibidir.

LLBLGenTest Page Screen

                Güncelle butonuna bastığımızda kayıtlar veritabanına eklenecektir.

LLBLGenTest Inserted Rows

                Kayıtları tablomuzda gördük ancak nasıl eklendiğine de bir bakalım.

LLBLGenTest Bulk Insert Sql Profiler Screen

                Sql Profilerda görüldüğü gibi tek bir bağlantı açılmış ve tüm insert işlemleri bu bağlantıda gerçekleştirilmiştir.

                Şimdi de bulkinsert  ile değil de her bir kaydı tek tek foreach döngüsü içerisinde insert etmeye çalışalım. Bu şekilde insert yapmak çok fazla kaydın bulunması durumunda bazı performans sıkıntıları oluşturacaktır. Önemsememiz gereken şey, database sunucusuna bir defa gidip tüm işlemleri bu gidişte bitirip dönmek olmalıdır. Insert ya da select işlemi ayırt etmeksizin bunu gerçekleştirmemiz gerekir.

                Önermediğimiz şekilde kullanıma bakalım. Buna göre sayfamızın CodeBehindını düzenlersek.

using System;

using System.Web.UI.WebControls;

using LLBLGenTest.EntityClasses;

using LLBLGenTest.WebApplication.Helpers;

 

namespace LLBLGenTest.WebApplication

{

    public partial class _Default : System.Web.UI.Page

    {

        protected void Page_Load(object sender, EventArgs e)

        {

            if (!IsPostBack)

            {

                BindArticle();

                BindCategoryCollection();

            }

        }

 

        private void BindCategoryCollection()

        {

            CategoryHelper categoryHelper = new CategoryHelper();

            CategoryList.DataSource = categoryHelper.Get();

            CategoryList.DataBind();

        }

 

        private void BindArticle()

        {

            ContentHelper contentHelper = new ContentHelper();

            var content = contentHelper.Get(1);

 

            TitleText.Text = content.Fields["Title"].DbValue.ToString();

            ContentText.Text = content.Fields["Text"].DbValue.ToString();

        }

 

        protected void UpdateButton_Click(object sender, EventArgs e)

        {

            ContentHelper contentHelper = new ContentHelper();

            foreach (ListItem categoryCheck in CategoryList.Items)

            {

                if (categoryCheck.Selected)

                {

                    contentHelper.Insert(new ContentCategoryEntity

                                                    {

                                                        CategoryId = Convert.ToInt64(categoryCheck.Value),

                                                        ContentId = 1

                                                    });

                }

            }

        }

    }

}

 

                Gördüğünüz üzere foreach döngüsü içerisinde seçilmiş olan herbir kategori için bir entity oluşturularak helper yardımıyla entitynin Save metotu çağırılarak tek tek insert işlemi gerçekleştirilmektedir.

                Bu işlem sonunda da yine veritabanına kayıtların aynı şekilde eklendiğini görürüz. Ancak  İşlemlerin arkaplanına baktığımızda bir farklılık görürüz.

LLBLGenTest Insert Sql Profiler Screen

                Sql Profilerda gördüğümüz üzere her bir kayıt için sql servera gidilmiş ve her bir kayıt için bir bağlantı açılmıştır. Bu şekilde aynı anda birden fazla kayıt eklenmesi gereken durumlarda doğru seçimi bu tarz bir inceleme sonucuna göre belirlemeliyiz. Belki tek tek bir koleksiyon nesnesine ekleyerek kullanıcıya ekliyormuş hissi vererek kullanıcının işlemleri bitirme noktasına geldiğinde tümünü bu şekilde bulk olarak kaydetme yoluna da gidilebilir bazı durumlarda. Dediğim gibi farklı caseler için farklı yöntemleri developer tercih etmelidir.

Etiketler : .Net , C# , Koleksiyonlar , LLBLGen Pro , Orm