Bir Micro-Orm Örneği olarak PetaPoco

PetaPoco kütüphanesini kullanmaya başlamadan önce, genel olarak orm kütüphanelerinden bahsetmek istiyorum. Bildiğimiz gibi hemen hemen tüm yazılım projelerinde orm (object relational mapping) aracı kullanıyoruz. EntityFramework, nhibernate, subsonic vs…

Bu araçlar yazılımcı olarak bizlerin işini oldukça kolaylaştırıyor. Insert, update, delete, select sql cümlelerini yazmamız gerekmiyor. Framework bizim yerimize bu işi yapıyor. First-level cache, second-level cache gibi mekanizmalar ile de bir performans avantajı sağlıyor. Bir obje yüklenmişse, tekrar tekrar veritabanından sorgu yapmadaya gerek kalmadan aynı objenin verilerine ulaşabiliyoruz. Code-First yapabiliyoruz. Yani önce poco objelerimizi tasarlayarak, karşılık gelen veritabanı tablolarının framework tarafından otomatik olarak yaratılmasını sağlayabiliriz.

Fakat getirdiği tüm kolaylıklara karşın, bazı dezavantajları da beraberinde getiriyor. Performans yönünden kritik bir uygulamamız olduğunu düşünelim. Öncelikle sql’i biliyor, nasıl performanslı sorgu yazacağımızı biliyorsak, orm kullandığımızda, bu bilgilerimizi kullanmak daha zor olacaktır. Framework daha performanslı sorgular üretilmesine olanak verse de bunun için, framework tarafını iyi bilmek gerekecektir. Sql bilenin basit bir şekilde yapabileceği şeyleri, frameworke yaptırmak için, uğraşılması gerekecektir. Sql aslında öğrenilmesi zor olmayan bir dildir.

Tablolarımızı manuel create etmek sorun değilse, ve sql konusunda biraz tecrübemiz varsa, bu tür kompleks framework kullanmak yerine, micro-orm kütüphanelerine yönelebiliriz.

Micro-orm, tabloların poco objelerine çevrilmesine olanak sağlayarak, orm ihtiyacımızı karşılayacaktır. Stackoverflow sitesi, kendi yazmış olduğu micro-orm kütüphanesi olan dapper kütüphanesini kullanmaktadır.

Bu yazıda micro-orm örneği olarak PetaPoco kütüphanesini inceleyeceğiz. Asp.net mvc 5 üzerinde çalışan, mysql veritabanını kullanan örnek bir uygulama üzerinden PetaPoco kullanım örneklerini inceleyeceğiz.

Öncelikle nuget paketini kuralım:

Install-Package PetaPoco -Version 5.1.153

Çalışan bir MySql veritabanı üzerinde petapocotestdb adında bir schema oluşturdum, ve Person tablosu create ettim.

CREATE TABLE `petapocotestdb`.`person` (
  `Id` INT NOT NULL AUTO_INCREMENT,
  `Name` VARCHAR(45) NULL,
  `Age` INT NULL,
  PRIMARY KEY (`Id`));

 

MySql.Data dll’lerine asp.net mvc uygulamasından referans veriyoruz.

mysqlreference

web.config dosyasına connection string bilgisi girilir (username ve password kendi db’nize göre değiştirilir):

  <connectionStrings>
    <add name="petapocotestdbconnection" connectionString="Database=petapocotestdb;     Data Source=localhost;User Id=myuser;Password=mypass" providerName="MySql.Data.MySqlClient" />    
  </connectionStrings>  

Asp.net mvc 5 uygulamamızın model klasörüne Person sınıfı tanımlıyoruz:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace petapocotest.Models
{
    public class Person
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

Index.cshtml dosyasına Person eklemeye yarayacak, aşağıdaki kodu yazıyoruz:

@model petapocotest.Models.Person
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div> 
    @using (Html.BeginForm("Index", "Home", FormMethod.Post))
    {
        @Html.AntiForgeryToken()
        <h4>Yeni kişi ekle</h4>
        <hr />
        @Html.ValidationSummary("")
        <table>
            <tr><td>@Html.LabelFor(m => m.Name)</td><td>@Html.TextBoxFor(m => m.Name)</td></tr>
            <tr><td>@Html.LabelFor(m => m.Age)</td><td>@Html.TextBoxFor(m => m.Age)</td></tr>
            <tr><td></td><td><input type="submit" value="Kaydet" /></td></tr>
        </table>
    }
    </div>
</body>
</html>

 

Kaydet butonuna bastığımızda, controllerda yazdığımız kod, insert işlemini gerçekleştirecektir. Artık PetaPoco’yu kullanmaya başlıyoruz:

using PetaPoco;
using petapocotest.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace petapocotest.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Index(Person person)
        {
            Database petapocotestDB = new Database("petapocotestdbconnection");

            petapocotestDB.Insert(person);

            return View();
        }
    }
}

Id’si bilinen bir kaydı bulmak için:

var person = petapocotestDB.Single<Person>(1);

Select:

var persons = petapocotestDB.Query<Person>("select * from person");

Paging, PetaPoco’nun Page classı sayesinde gerçekleşiyor :

Page<Person> m = petapocotestDB.Page<Person>(1, 20, "select * from person ORDER BY Id");

Uygulamalarımızda one-to-many ilişkisine sahip bir obje hiyerarşisine ihtiyaç duyabiliriz. Örnek uygulamamızda, Person classının rolleri olduğunu düşünelim. Bir kişinin pek çok rolünün olduğunu düşünelim. Örneğin A kişisinin birden fazla rolü var; idareci, muhasebe yetkilisi vs…

Önce tablomuzu create ediyoruz:

CREATE TABLE `petapocotestdb`.`role` (
  `Id` INT NOT NULL AUTO_INCREMENT,
  `PersonId` INT NULL,
  `Name` VARCHAR(45) NULL,
  PRIMARY KEY (`Id`));

Role sınıfını oluşturuyoruz:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace petapocotest.Models
{
    public class Role
    {
        public long Id { get; set; }
        public long PersonId { get; set; }
        public string Name { get; set; }
    }
}

Person modelini değiştirelim:

using PetaPoco;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace petapocotest.Models
{
    public class Person
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

        [Ignore]
        public List<Role> Roles { get; set; }
    }
}

Roles field’ına ignore dememizin sebebi, PetaPoco’nun single metodunu çağırırken, veritabanında olmayan bir field olmadığı için hata vermesi.

one-many ilişkisini kurmak için bir relator sınıfı oluşturmamız gerekiyor:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace petapocotest.Models
{
    public class PersonRoleRelator
    {
        public Person current;
        public Person MapIt(Person person, Role role)
        {
            // Terminating call.  Since we can return null from this function
            // we need to be ready for PetaPoco to callback later with null
            // parameters
            if (person == null)
                return current;

            // Is this the same author as the current one we're processing
            if (current != null && current.Id == person.Id)
            {
                // Yes, just add this post to the current author's collection of posts
                current.Roles.Add(role);

                // Return null to indicate we're not done with this author yet
                return null;
            }

            // This is a different author to the current one, or this is the 
            // first time through and we don't have an author yet

            // Save the current author
            var prev = current;

            // Setup the new current author
            current = person;
            current.Roles = new List<Role>();
            current.Roles.Add(role);

            // Return the now populated previous author (or null if first time through)
            return prev;
        }
    }
}

Artık person listesini petapoco ile çektiğimizde, person objesinin içerisinde yer alan roles listesini otomatik olarak doldurmuş olacağız:

var personList = petapocotestDB.Fetch<Person, Role, Person>(
                new PersonRoleRelator().MapIt,
                "SELECT * FROM person LEFT JOIN role ON role.PersonId = person.Id " +
                "ORDER BY role.Id"
                );

Son olarak PetaPoco dokümantasyonunun olduğu sayfaya link verelim: http://www.toptensoftware.com/petapoco/

 

 

 

 

 

1 thought on “Bir Micro-Orm Örneği olarak PetaPoco”

Yorum bırakın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Scroll to Top