OptimisticLock using Fluent NHibernate

OptimisticLock ve PessimisticLock konuları hakkında Optimistic Lock Nedir ? Pessimistic Lock Nedir ? Data concurrency yazımızda bahsetmiştik. Kısaca hatırlatmak gerekirse;farklı thread'ler de aynı row üzerinde işlem yapılırken herhangi bir lock işlemi olmadan update edilmek istenen verinin bayat olup olmadığını o verinin kayıtlı olduğu tabloda yer alan versiyon numarası olarak da adlandırılan bir column'da bulunan değeri kontrol eder ve eğer versiyon eşleşmiyorsa yani veri bayat ise işlem geri çekilir.

Bu yazıda ise Nhibernate kullanarak optimistic lock nasıl yapılır bunu inceleyeceğiz. Daha önceki Unit of Work Interceptor, Castle Windsor, NHibernate ve Generic Repository yazısında geliştirdiğimiz proje üzerinden ilerleyelim. Bir web api projesi oluşturmuştuk ve nuget üzerinden Fluent Nhibernate'i yüklemiştik. İçerisinde User ve Address adında iki tane tablomuz bulunuyordu. Nhibernate için optimistic lock konfigurasyonu mapping işlemi yapılırken belirtiliyor. Bizde öncelikle versiyonlamak veya optimistic lock uygulamak istediğimiz entity'ler için bir base model oluşturalım.

    public abstract class VersionedEntity
    {
        public virtual int EntityVersion { get; set; }
    }

User modelimiz ise yukarıda tanımladığımız modelden inherit olsun ve aşağıdaki gibi UserMapping.cs içerisinde konfigurasyonlarımızı yapalım.

 

    public class User : VersionedEntity
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual string SurName { get; set; }
    }

    public class UserMap : ClassMap<User>
    {
        public UserMap()
        {
            Table("Users");
            Id(x => x.Id);
            Map(x => x.Name);
            Map(x => x.SurName);

            // versiyon işlemi için kullanılacak column
            Version(X => X.EntityVersion);
            
            // optimistic lock'ı versiyonlama üzerinden aktif hale getiriyoruz
            OptimisticLock.Version();
        }
    }

Database de Users tablomuzda EntityVersion adında bir column yaratılacak ve bu column o row için yapılan her bir update işleminde 1 artacaktır.

Konfigurasyon işlemi bu kadar şimdi test yapalım. Aşağıdaki gibi AddnewUser metoduna postman üzerinden sırayla 1 insert 2 get 2 put(update) request'i atalım.

İlk insert işlemi sonrasında db deki kayıt aşağıdaki gibi EntityVersion= 1 şeklinde olacaktır.

Sonrasında ardı ardına 2 get işlemi yapıp db deki kaydı alalım ve sonrasındaki ilk update işlemi sonrasında kaydımız aşağıdaki gibi EntityVersion = 2 şeklinde güncellenecektir.

İkinci get işlemini yapan transaction için yani üstte update yapılmışken eline stale/bayat veriye sahipken update işlemi yapmaya çalıştığında diğer bir değişle db de ki EntityVersion = 2 iken ikinci işlemin elinde EntityVersion = 1 olan kayıt varken update yapmaya çalıştığında aşağıdaki gibi bir exception throw edilir.

Hata mesajı bize o row'un bize başkabir transaction tarafından update veya delete edildiğini belirtmekte. Bu durumu yaşamamak için ikinci işlem için tekrardan db de bulunan kayıt get edilip üzerinden bir update işlemi yapıldığında db deki son görüntüsü aşağıdaki gibi EntityVersion = 3 şeklinde olacaktır.

 

Optimistic Lock için yazımız buraya kadar. Yukarıda da belirttiğim gibi örnek kodlar Unit of Work Interceptor, Castle Windsor, NHibernate ve Generic Repository yazısında bulunmakta. Eksik kalan yerler için ordan devam edebilirsiniz.

Add comment