Monday, October 16, 2017

ProjectBase ile DataTable Yerine Önceden Tanımlı Nesne Kullanarak Veri Çekme (Tip Belirtimli - Typed)

Daha önceki yazılarda DataTable üzerinde veri çekme örneği yapmıştık. DataTable ile yapılan işlemler "Typed" yani belirli türlü olmadığı için kodlamayı zorlaştırmaktadır. Şimdi kendi oluşturduğumuz bir sınıfa ait nesneyi verileri tutmak için kullanacağız. Yine "EMPLOYEES" tablosunu kullanalım ve önce sınıfı aşağıdaki gibi oluşturalım:

public class EMPLOYEE
{
    public string FIRST_NAME { get; set; }
    public string LAST_NAME { get; set; }
    public decimal SALARY { get; set; }
    public DateTime? HIRE_DATE { get; set; }

}

Burada dikkat edilmesi gereken husus yazacağımız sorgudan gelecek olan sütun isimlerinin "Property" isimleri ile eşleşmesidir. Eşleme büyük-küçük harfe duyarlı değildir. Şimdi bu sınıfı kullanacak veri çekme kodlarını yazalım:

var db = DatabaseFactory.GetDbObject();
var gen = QueryGeneratorFactory.GetDbObject();

gen.SelectText = "select * from employees where employee_id < 112";

List<EMPLOYEE> employees = db.GetObjectList<EMPLOYEE>(gen.GetSelectCommandBasic());

Yukarıdaki kod çalıştırıldığında id numarası 112'den küçük kayıtları yazdığımız sınıfın bir listesi olarak elde edeceğiz.

"Bu yazıda "Oracle Managed Provider", Oracle 11g Express Edition ve HR şeması test verileri kullanılmıştır."

"https://github.com/vyigity/ProjectBase"

Sunday, October 15, 2017

ProjectBase Data Access and Utility Library - ProjectBase Veri Erişim ve Yazılım Destek Kütüphanesi

ProjectBase (PB) is a Utility and Data Access library. PB designed with a database independent interface oriented approach to ensure extentibility and reliablity. PB's codes can be changed or manipulated easily. PB can be installed with nuget package manager console:
PM> Install-Package vyigity.ProjectBase -Version 4.0.0

PB has 3 type of data access:
  • Automatic Connection Management: Using single connection object and while executing a command, connection is opened and closed automatically.
  • Manuel Connection Management: Using single connection object and connection is opened and closed by developer manually.
  • Transaction Mode: PB supports PL/SQL type code writing of transactional processes. PB creates transactions and manages them automatically.
PB currently supports Oracle (Managed-Unmanaged Provider), SQL Server databases and OleDb. PB supports MySql provider with v2.0.0 and PostgreSQL provider with v3.0.0.
Also PB supports low level object mapping features.

Project Adress:
For introduction:
For connection management examples:
For transactions examples:
For DML examples:
For parametric database procedures and functions examples:

ProjectBase ve QueryGenerator ile Veri Tabanı Prosedür İşlemleri

QueryGenerator ile veri tabanı prosedür veya fonksiyonlarına erişmek için öncelikle örnek veri tabanı fonksiyonlarını oluşturalım:

FUNCTION "GETUSERNAME" (
  "PARAM1" IN NUMBER) RETURN varchar2 IS

  RETURN_VAL varchar2(150);

BEGIN 

  select FIRST_NAME ||' ' || LAST_NAME into RETURN_VAL from employees where employee_id = PARAM1;
  
  RETURN RETURN_VAL;

END;


FUNCTION "GETSALARY" (
  "PARAM1" IN NUMBER) RETURN number IS

  RETURN_VAL NUMBER;

BEGIN 
  
  select SALARY into RETURN_VAL from employees where employee_id = PARAM1;

  RETURN RETURN_VAL;

END;

Yukarıda string değer döndüren "GETUSERNAME" ve decimal değer döndüren "GETSALARY" fonksiyonlarını oluşturduk. Aşağıda gibi bu fonksiyonları .NET projemiz içinde kullanabiliriz:

var db = DatabaseFactory.GetDbObject();
var gen = QueryGeneratorFactory.GetDbObject();

gen.ProcedureName = "GETSALARY";
gen.AddDataParameter("RETURN_VAL", DbType.Decimal, null, 150, System.Data.ParameterDirection.ReturnValue);
gen.AddDataParameter("PARAM1", 100);

db.ExecuteQuery(gen.GetProcedure());

var return_val = gen.GetParameterValue("RETURN_VAL");

string gen2 = QueryGeneratorFactory.GetDbObject();

gen2.ProcedureName = "GETUSERNAME";
gen2.AddDataParameter("RETURN_VAL", DbType.String, null, 150, System.Data.ParameterDirection.ReturnValue);
gen2.AddDataParameter("PARAM1", 100);

db.ExecuteQuery(gen2.GetProcedure());

decimal return_val2 = gen2.GetParameterValue("RETURN_VAL");

Yukarıda görüldüğü üzere QueryGenerator ile standart bir kod arayüzü ile fonksiyon ve prosedür erişimleri yapılabilmektedir.

"Bu yazıda "Oracle Managed Provider", Oracle 11g Express Edition ve HR şeması test verileri kullanılmıştır."

"https://github.com/vyigity/ProjectBase"

Saturday, October 14, 2017

ProjectBase ile QueryGenerator kullanarak parametrik DML işlemleri

"QueryGenerator" (QG) standart olarak parametrik veri tabanı işlemlerini gerçekleştirilmesi sağlayan sınıftır. Parametrik işlemler SQL injection gibi güvenlik açıklarına karşı kesinlikle tercih edilmesi gereken bir yöntemdir. Parametrik işlemlerde kullanılan ve sql texti içinde yer alan bir sözün parametre olup olmadığının anlaşılmasını sağlayan ve verita banına göre değişebilen bazı karakterler vardır. Bunlar SQL Server veri tabanı için "@", Oracle veri tabanı için ":" karakterleridir. Örneğin SQL Server içi parametre yazılacaksa "@Param" şeklinde, Oracle için yazılacaksa ":Param" şeklinde yazılır. QG sınıfı standart olarak ":Param" şeklinde yazılacak şekilde hazırlanmıştır.

Aşağıdaki kod bloku ile QG ile nasıl veri çekilebileceği gösterilmiştir:

var gen = QueryGeneratorFactory.GetDbObject();
var db = DatabaseFactory.GetDbObject();
string sql = "select * from employees where employee_id = :ID";

gen.SelectText = sql;
gen.AddFilterParameter("ID", 100);

var dt = db.ExecuteQueryDataTable(gen.GetSelectCommandBasic());

Yukarıdaki örnekte görüldüğü üzere ":ID" parametresi ile bir filterparameter oluşrulmuş ve 100 id numaralı kişinin bilgileri çekilmiştir.

QG ile Update ve Insert işlemleri de kolaylıkla yapılabilmektedir. Aşağıdaki kod bloğunda 101 id numaralı kişinin bilgileri güncellenmiştir:

var db = DatabaseFactory.GetDbObject();
var gen = QueryGeneratorFactory.GetDbObject();
gen.TableName = "EMPLOYEES";
gen.AddDataParameter("FIRST_NAME", "VELI YIGIT");
gen.AddDataParameter("LAST_NAME", "YOLCU");
gen.AddFilterParameter("Param1", 101);
gen.FilterText = "WHERE employee_id = :Param1";

db.ExecuteQuery(gen.GetUpdateCommand());

Yukarıdaki kod bloğundan anlaşıldığı üzere sadece değiştirilecek alanların parametre olarak eklenmesi yeterlidir. Gerekli update komutu QG tarafından oluşturulmaktadır. Burada dikkat edilmesi  gereken nokta filtre içinde yer alan parametreler "FilterParameter" olarak eklenmelidir.

QG ile Insert işlemi aşağıdaki gibi yapılabilmektedir:

var db = DatabaseFactory.GetDbObject();
var gen = QueryGeneratorFactory.GetDbObject();
gen.TableName = "EMPLOYEES";
gen.AddDataParameter("EMPLOYEE_ID", "300");
gen.AddDataParameter("FIRST_NAME", "VELI YIGIT");
gen.AddDataParameter("LAST_NAME", "YOLCU");
gen.AddDataParameter("EMAIL", "vyigity@deneme.com");
gen.AddDataParameter("HIRE_DATE", new DateTime(2017,10,14));
gen.AddDataParameter("JOB_ID", "SH_CLERK");

db.ExecuteQuery(gen.GetInsertCommand());

Update komutuna benzer olarak Insert komutunda da eklenecek alanların DataParameter olarak eklenmesi yeterlidir.

"Bu yazıda "Oracle Managed Provider", Oracle 11g Express Edition ve HR şeması test verileri kullanılmıştır."

"https://github.com/vyigity/ProjectBase"

Sunday, October 8, 2017

ProjectBase ile Veri Tabanı Bağlantı Türlerine Göre İşlemler

ProjectBase "TransactionMode" dışında bağlantı kontrolüne göre 2 yöntem içermektedir. "ManuelConnectionManagement" ile veri tabanı işlemleri şöyle yapılabilmektedir:

IDatabase2 db = DatabaseFactory.GetDbObject();
db.ExecuteQuery("update employees set salary = 3000 where employee_id = 100");

//Yeni veri tabanı bağlantısı kuruldu
//salary = 3000 oldu
//Bağlantı kesildi

db.ExecuteQuery("update employees set salary = 24000 where employee_id = 100");

//Yeni veri tabanı bağlantısı kuruldu
//salary = 24000 oldu
//Bağlantı kesildi

Yukarıdaki kod örneğinde gösterildiği üzere her işlemde bağlantı kurulup kapatılmaktadır. Art arda işlemlerde bu durum performans sorunu çıkaracağından bu durumda "ManuelConnectionManagement" tercih edilmelidir. Bu durumda aynı işlem iki farklı kod biçiminde yazılabilir.

IDatabase2 db2 = DatabaseFactory.GetDbObject(DbSettings.ManuelConnectionManagement);
db2.ExecuteQuery("update employees set salary = 3000 where employee_id = 100");

//Veritabanı bağlantısı kuruldu
//salary = 3000 oldu
//Bağlantı açık bırakıldı

db2.ExecuteQuery("update employees set salary = 24000 where employee_id = 100");

//Eski bağlantısı kullanıldı
//salary = 24000 oldu
//Bağlantı açık bırakıldı

db2.CloseConnection();

//Bağlantı kesildi.

Yukarıdaki örnekte görüldüğü üzere "CloseConnection" çağrılmadan bağlantı sonlandırılmamaktadır. Aynı kod aşağıdaki biçimde de yazılabilir:

using (IDatabase2 db = DatabaseFactory.GetDbObject(DbSettings.ManuelConnectionManagement))
{
    db.ExecuteQuery("update employees set salary = 3000 where employee_id = 100");

    //Veritabanı bağlantısı kuruldu
    //salary = 3000 oldu
    //Bağlantı açık bırakıldı

    db.ExecuteQuery("update employees set salary = 24000 where employee_id = 100");

    //Eski bağlantısı kullanıldı
    //salary = 24000 oldu
    //Bağlantı açık bırakıldı           
}

//Bağlantı kesildi.

"Bu yazıda "Oracle Managed Provider", Oracle 11g Express Edition ve HR şeması test verileri kullanılmıştır."

"https://github.com/vyigity/ProjectBase"

Saturday, October 7, 2017

ProjectBase ile Veri Tabanı İşlemleri (Transaction Örneği)

"ProjectBase" kütüphanesi otomatik transaction yönetimi ve connection yönetimi yapmaktadır. Veritabanı erişim sınıfları 3 modda çalışmaktadır. Bunlar:

* AutoConnectionManagement
* ManuelConnectionManagement
* TransactionMode

Veri tabanı erişim sınıfları ön tanımlı olarak "AutoConnectionManagement" modda çalışmaktadır. Bu modda klasik olarak her işlemde bağlantı açılıp işlem sonlandığında bağlantı kapatılmaktadır. Bu yöntem sıralı işlemlerde yavaş çalıştığından "ManuelConnectionManagement" modunda bağlantının ne zaman açılıp kapanacağı yazılımcı tarafından yönetilerek performans kazanımı yapılabilmektedir. TransactionMode ise PL/SQL tipinde kod yazımı için geliştirilmiştir.

Aşağıdaki örnekte TransactionMode kullanılarak nasıl işlem yapılacağı gösterilmiştir:

using (IDatabase2 db = DatabaseFactory.GetDbObject(DbSettings.TransactionMode))
{
    //salary = 24000

    db.ExecuteQuery("update employees set salary = 3000 where employee_id = 100 ");
    db.Commit();

    //salary = 3000 oldu

    db.ExecuteQuery("update employees set salary = 5000 where employee_id = 100 ");
    db.Commit();

    //salary = 5000 oldu

    db.ExecuteQuery("update employees set salary = 6000 where employee_id = 100 ");
    db.ExecuteQuery("update employees set manager_id = 101 where employee_id = 100 ");
    db.Commit();

    //salary = 6000 ve manager 101 oldu

    db.ExecuteQuery("update employees set salary = 10000 where employee_id = 100 ");
    db.ExecuteQuery("update employees set manager_id = null where employee_id = 100 ");
    db.RollBack();

    //salary = 6000 ve manager 101 kaldı

    db.ExecuteQuery("update employees set salary = 24000 where employee_id = 100 ");
    db.ExecuteQuery("update employees set manager_id = null where employee_id = 100 ");
    db.Commit();

    //salary = 24000 ve manager null oldu

    db.ExecuteQuery("update employees set salary = 50000 where employee_id = 100 ");

    throw new Exception("Fatal Error!");

    //Son işlem geri alındı.
}

Yukarıda görüldüğü gibi veri tabanı erişim sınıfı  transaction yönetimini otomatik olarak gerçekleştirdi. Yani yukarıdaki kod incelendiğinde 6 tane transaction otomatik olarak oluşturulmuş ve işlenmiştir. Veri tabanı erişim sınıfı ön tanımlı olarak hata olması durumunda rollback yapmaktadır. Bu yüzden son işlem geri alınmıştır.

"Bu yazıda "Oracle Managed Provider", Oracle 11g Express Edition ve HR şeması test verileri kullanılmıştır."

"https://github.com/vyigity/ProjectBase"

Veri Erişim Katmanına Giriş - Introduction to DAL (Data Access Layer)

Günümüzde yazılım projelerinde katmanlı mimari en önemli özelliklerden biridir. Katmanlı mimaride bir katman istenildiğinde başka bir projede aynen kullanılabilmekte böylece kod tekrarı azaltılmakta ve güvenilirlik büyük ölçüde artırılmaktadır.

Bir çok yazılım projesinin en önemli parçalarından biri veri erişim katmanıdır çünkü bu katman aracılığı ile veri tabanı işlemleri yürütülür. Bu yazıda kendi yazdığım "ProjectBase" (PB) isimli DAL katmanına giriş yapacağım. Proje kodlarına buradan ulaşabilirsiniz.

DAL katmanı için en önemli noktalar  tutarlılık, güvenilirlik, çok biçimlilik (Polimorfizm) ve genişletilebilirliktir. PB kütüphanesi çok biçimlilik ve genişletilebilirlik için "Interface" tabanlı bir yapıda oluşturulmuştur. PB kütüphanesi ile iş katmanında yazılan kodlarda değişiklik yapılmadan veri tabanı değişikliği kolaylıkla yapılabilmektedir. Ayrıca PB içinde tanımlı interface kullanılması ile istenildiği kadar "provider" sınıf yazılabilir ve bu sınıflar özelleştirilebilir.

Şimdi PB ile veri okuma işlemi yapalım:

* Veri tabanı olarak Oracle 11g Express Edition kullanacağım.  Veri tabanını Oracle'ın resmi sitesinden ücretsiz olarak indirebilirsiniz.

* Provider olarak Oracle "ManagedDataAccess" kullanacağım.

Veri tabanı kurulumunu yaptıktan sonra web.config içerisinde bağlantı stringi aşağıdaki gibi tanımlanmalıdır.

<connectionStrings>
      
    <add name="Context" connectionString="DATA SOURCE=XE;PASSWORD=hr;USER ID=hr" providerName="Oracle.ManagedDataAccess.Client" />
    
</connectionStrings>

Burada providerName önemlidir. Erişim sınıfları burada yazan provider bilgisine göre ilgili sınıfları seçecektir.

DAL katmanının kurulumu için "ProjectBase" kütüphanesini indirip projeye eklemek kurulum için yeterlidir.

using (IDatabase2 db = DatabaseFactory.GetDbObject())
{
    var dt = db.ExecuteQueryDataTable("select * from employees");
}

Yukarıdaki kod bloğu ile "Employees" tablosunda yer alan bütün veriler çekilip "DataTable" nesnesi olarak döndürülmektedir. Oracle veri tabanı içinde "HR" şemasında test için küçük bir veri tabanı servis edilmektedir. "Employees" tablosu bu veri tabanının içindedir.

ProjectBase kütüphanesi Oracle ve SQL veri tabanlarını ve OleDb erişimini desteklemektedir.