DbUp ile Veritabanı Değişiklik (Migration) Yönetimi

Daha önce blogumuzda fluentmigrator adlı dotnet kütüphanesinin tanıtımını yapmıştık. FluentMigrator ile c# sınıflarını kullanarak veritabanı güncellemelerini (migration) otomatize edebiliyorduk. Örneğin test veritabanı için kullandığımız veritabanı değişikliklerini aynı şekilde başka ortamlara (alfa, beta, canlı ortamlara) kolayca uygulayabiliyorduk. Peki bu tür işlemler için neden sql scriptlerini doğrudan kullanmıyoruz diye insanlar sormuşlar ve sql betik bazlı kütüphaneler geliştirmişlerdir. DbUp bu kütüphanelerin en bilinenlerindendir.

Neden Sql?

Sql piyasada çok uzun zamandır bilinen ve kullanılan standardı olan veritabanı izleme ve güncelleme dilidir.

Ayrı bir yazılım katmanı ve yükü getirmeden doğrudan veritabanı işlemlerini yapmaya yarar. Gerçekten de c# veya java gibi dillerde kullanılan ado.net ve jdbc kütüphanelerinin de yaptığı şey, arka planda sql betiklerini kullanarak veritabanı işlemlerini yürütmektir. Bu sebepten çoğu durumda daha performanslı çalışacak ve daha az kaynak harcanacaktır.

Sql veriler konusunda çok kullanışlı ve esnek bir dildir. Kolayca öğrenilebilir ve veritabanı işlemlerinde her tür işi zorlanmadan yapabilmeyi sağlar. Veritabanının yerel dili olduğu için henüz programlama dillerinde olmayan özellikleri sql sayesinde kullanabiliriz.

Biraz sql bilen biri için yapabildiğimiz sıradan şeyleri düşünelim:

  • Varolan bir tabloya yeni kolon eklemek
  • Bir kolonun veri tipini değiştirmek
  • Veriler yeni veri tipi ile uyumsuz ise, veritipine uygun bir şekle dönüştürmek
  • Kayıtları bir tablodan alıp başka tabloya kopyalamak

Yani kısaca sql kötü bir şey değil aksine faydalı, çoğu durumda hayat kurtaran bir araçtır.

DbUp

Github adresi http://dbup.github.io/ olan açık kaynak kodlu, c# ile yazılmış, dotnet framework ve dotnet core çatılarını destekleyen bir kütüphanedir. Java dünyasında bilinen benzer bir mantıkla çalışan flyway ve liquibase kütüphanelerine alternatif olarak kullanılabilir.

Veritabanı değişikliklerini sql betikleri olarak yazıyoruz. DbUp, henüz çalıştırılmamış betikleri bulup çalıştırarak veritabanımızı güncel hale getirmektedir. Sistemde hali hazırda çalışmış olan sql betiklerini, schemaversions isimli kendi oluşturduğu bir tabloya yazarak takibini yapmaktadır.

DbUp kütüphanesinin belki eksik olarak nitelendirilebilecek yanı, veritabanı değişikliklerini geri alma imkanı sunmamasıdır. Flyway örneğin bu imkanı sunmaktadır. Fakat yine de geri alma işleminin riskli ve otomatize etmeye çok uygun olmadığını düşünürsek, bu özelliğin olmazsa olmaz bir şey olmadığını söyleyebiliriz.

Örneğin bir tabloyu içindeki verilerle birlikte sildiğimiz zaman, ya da bir tekil indeksi sildiğimiz zaman geri almanın her zaman mümkün olmadığı durumlar oluşacaktır. Çünkü arada veriler değişecek belki geri tekil index oluştururken hata alacağız. Bu ve bunun gibi pek çok sorunla karşılaşabiliriz.

Install-Package DbUp

Nuget paketini kullanarak DbUp kütüphanesini projemize ekleyebiliriz.

Piyasada yaygın kullanılan veritabanlarının tamamını desteklemektedir. Ayrıca gerektiği durumda veritabanı değişiklikleri için, c# sınıfı yazmaya da imkan vermektedir. Github reposundaki örnek uygulamada böyle bir kodu inceleyebilirsiniz:

DbUp/src/Samples/SampleApplication/Scripts/Script0005 – ComplexUpdate.cs

IScript interface’ını gerçekleştiren örnek bir C# sınıfında aşağıdakine benzer işler yapabilirsiniz.

public string ProvideScript(Func<IDbCommand> dbCommandFactory)
{
    var cmd = dbCommandFactory();
    cmd.CommandText = @"SELECT count(*) FROM products";
    cmd.CommandType = CommandType.Text;

    var myValue = (decimal)cmd.ExecuteScalar();

    if (myValue == 0)
    {

       ---------

       var cmdOldProducts = dbCommandFactory();
       cmdOldProducts.CommandText = "SELECT ID FROM oldproducts";
       cmdOldProducts.CommandType = CommandType.Text;

       var readerOldProducts = cmdOldProducts.ExecuteReader();

       var scriptBuilder = new StringBuilder();

       while (readerOldProducts.Read())
       {
          var oldProductId = (decimal)readerOldProducts["ID"];
          scriptBuilder.AppendLine("INSERT INTO PRODUCTS (ID) VALUES (" + oldProductId + ")");
       }
 
       return scriptBuilder.ToString();
   }
   else 
   {
       return "";
   }
}

Örnek biraz abartı oldu fakat neler yapabileceğimizi görmek açısından bu örneği yazdım. Çoğu durumda sql betikleri zaten işimizi görecektir.

 

 

Yorum bırakın

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

Scroll to Top