Azure Storage Serisi #6 – Azure Table Storage ve Asp.NET Core İle Kullanımı

Merhaba,

Azure Storage Yazı Dizisinin bu altıncı makalesinde Azure Table Storage servisi üzerine incelemede bulunuyor olacağız.

Azure Table Storage Nedir?

Azure Table Storage, bir NoSQL veritabanı türevidir. Primary Key ve Foreign Key ihtiyacı olmaksızın veri tutmamız gerektiğinde bu veriyi ilişkisel veritabanında tutmaktansa NoSQL’de tutmayı tercih edebiliriz. NoSQL açılımsal olarak ‘Not Only SQL’ yani ‘Sadece SQL Değil’ diyerek, bu ve bunun gibi ilişkisel bir tasarım gerektirmeyen durumlarda standart SQL’in zaten var olan yoğunluğu içerisinde ekstradan maliyeti arttırmaksızın NoSQL yaklaşımını benimsemiş bir veritabanı üzerinden çözüm getirilmesi ve böylece maliyetten düşülerek verisel işlemlerde hız ve verimin arttırılması fikrini ortaya koymaktadır.

NoSQL, yapısal olarak veriler üzerinde statik alan tanımlamalarından ziyade daha esnek olan ve ihtiyaca binaen dinamik alan tanımlamasına imkan verdiğinden dolayı ilişkisel veritabanlarında olan sert kuralları aşabilmemizi sağlamakta ve bu esnekliğin getirisi olan verimlilikten dolayı tercih edilmektedir. NoSQL hakkında daha detaylı ekstra bilgiler edinmek için buradaki makaleyi okumanızı tavsiye ederim.

NoSQL ile Relational yaklaşımları birlikte kullanıldığında daha güçlü, performanslı ve verimli olmaktadır.

Azure Table Storage’ı Neden Kullanmalıyız?

Azure Table Storage, NoSQL yaklaşımı benimsediğinden dolayı uygulamanızın ihtiyaçları geliştikçe verilerinizi uyarlamak daha kolay olacaktır. Benzer hacimlerdeki veriler için geleneksel SQL yöntemlerine nazaran daha düşük maliyette sorgulamalar yapmanızı sağlayacaktır. Ayrıca OData protokolü ile yapılan sorgulamalarda NoSQL yaklaşımları oldukça elverişli bir sonuç doğurmaktadır.

Azure Storage Table’ın transaction desteği bulunmamaktadır. Bu durum kesinlikle NoSQL veritabanları için genellenmemelidir. Örneğin; MongoDB NoSQL yaklaşımını benimsemiş bir veritabanıdır ve transaction desteği bulunmaktadır.

Azure Table Storage Kavramları Nelerdir?

Azure Storage Serisi #6 - Azure Table Storage

  • URL Format
    Azure Storage Table account’u aşağıdaki gibi bir url şablonu kullanır.
    https://<storage account> .table.core.windows.net/

    Bu adresi kullanarak direkt erişimde sağlayabilir yahut OData protokolü ile url üzerinden sorgulamada bulunabilirsiniz.

  • Entity
    Bir olguya karşılık gelen ve sadece o olguyu modelleyen bir bütündür. Azure storage’da bir entity’nin boyutu en fazla 1 MB olabilir ve en fazla 256 property barındırabilir. NoSQL’de ki(MongoDB) document’e karşılık gelir.
  • Table
    Table’lar entitylerin tutulduğu koleksiyonlardır. NoSQL yaklaşımını benimsedikleri için içerisinde tutulacak entityler tek tip olmak zorunda değildirler. NoSQL’de ki(MongoDB) collection’a karşılık gelir.
  • Properties
    Entity içerisinde verileri key/value formatında depolayabilmeye yarar. Yukarıda bahsedildiği gibi bir entity içerisinde en fazla 256 adet bulunabilir.

Azure Table Storage’a bir veri eklendiğinde ilgili entity içerisine default olarak ‘Row Key’, ‘Partition Key’ ve ‘Timestamp’ alanları eklenir.

Row Key; Primary Key gibi düşünülebilir. Eşsiz bir değerdir.

Partition Key; entityleri gruplama ve hızlı arama için kullanılır. Örneğin; User tablosunda tüm userların bulunduğu şehirleri partition key olarak işaretlememiz şehirleri gruplayacak ve arama esnasında ilgili şehir dışında olan userları aramaksızın sürece büyük avantaj sağlayacaktır.

Timestamp; Zaman damgası, verinin eklendiği tarihi tutacaktır.

Azure Table Storage, LINQ’i destekler…

Asp.NET Core İle Azure Table Storage Kullanımı

Azure Table Storage’ı Asp.NET Core ile kullanabilmek için öncelikle bir Class Library içerisinde uygulamadan bağımsız Azure Storage ile iletişim kuran yapılanma oluşturulmalıdır. Ardından ilgili yapılanmanın uygulama tarafından dependency edilerek kullanılması yazılımsal açıdan daha kullanışlı ve efektif bir yöntem olacaktır.

Bunun için aşağıdaki adımları sırasıyla uygulayınız;

  • Adım 1
    Herhangi bir isimde bir class library oluşturunuz. Ben ‘AzureStorage’ ismini tercih edeceğim.
  • Adım 2
    İlgili class library’e ‘Microsoft.Azure.Cosmos.Table‘ paketini yükleyiniz.
    Azure Storage Serisi #6 - Azure Table Storage ve Asp.NET Core İle Kullanımı
  • Adım 3
    Azure Table Storage’da tutulacak datanın entity’sini oluşturunuz. Bizler burada ‘Product’ isminde bir entity oluşturarak örneklendirmede bulunacağız.

        public class Product : TableEntity
        {
            public string Name { get; set; }
            public string No { get; set; }
        }
    

    Burada dikkat edilmesi gereken husus, oluşturulan entitylerin ‘TableEntity’ sınıfından türemesi gerekliliğidir.

    ‘TableEntity’ sınıfının detayına bakarsanız eğer ‘PartitionKey’, ‘RowKey’ ve ‘Timestamp’ propertyleri içerisinde hazır gelmekte ve böylece kendisinden türeyen entity’e kalıtımsal olarak ilgili özellikler kazandırılmaktadır.

  • Adım 4
    Ardından artık NoSQL sorgularını gerçekleştirebilmek ve storage ile ilgili işlevleri yerine getirebilmek için ‘INoSQLStorage’ isminde bir interface oluşturunuz ve içeriğini aşağıdaki gibi tasarlayınız.

        public interface INoSQLStorage<T>
        {
            Task<T> Add(T entity);
            Task<T> Get(string rowKey, string partitionKey);
            Task<T> Delete(string rowKey, string partitionKey);
            Task<T> Update(T entity);
            IQueryable<T> All();
            IQueryable<T> Query(Expression<Func<T, bool>> query);
        }
    
  • Adım 5
    ‘TableStorage’ isminde bir class oluşturunuz ve yukarıda oluşturulan ‘INoSQLStorage’ interface’inden implemente ediniz ve içeriğini aşağıdaki gibi geliştiriniz.

        public class TableStorage<T> : INoSQLStorage<T> where T : TableEntity, new()
        {
            CloudTableClient _cloudTableClient;
            CloudTable _cloudTable;
            public TableStorage()
            {
                CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;Acco******s1BxP4MT7tTeHbNe/WljTCZQt7RfMr5UqVbKnuGTrtA=*********re.windows.net");
                _cloudTableClient = cloudStorageAccount.CreateCloudTableClient();
                _cloudTable = _cloudTableClient.GetTableReference(typeof(T).Name);
                _cloudTable.CreateIfNotExists();
            }
            public async Task<T> Add(T entity)
            {
                TableOperation operation = TableOperation.InsertOrMerge(entity);
                return (await _cloudTable.ExecuteAsync(operation)).Result as T;
            }
            public IQueryable<T> All() => _cloudTable.CreateQuery<T>().AsQueryable();
            public async Task<T> Delete(string rowKey, string partitionKey)
            {
                TableOperation operation = TableOperation.Delete(await Get(rowKey, partitionKey));
                return (await _cloudTable.ExecuteAsync(operation)).Result as T;
            }
            public async Task<T> Get(string rowKey, string partitionKey)
            {
                TableOperation operation = TableOperation.Retrieve<T>(partitionKey, rowKey);
                return (await _cloudTable.ExecuteAsync(operation)).Result as T;
            }
            public IQueryable<T> Query(Expression<Func<T, bool>> query) => _cloudTable.CreateQuery<T>().Where(query);
            public async Task<T> Update(T entity)
            {
                TableOperation operation = TableOperation.Replace(entity);
                return (await _cloudTable.ExecuteAsync(operation)).Result as T;
            }
        }
    

    Yukarıdaki kod bloğunu incelerseniz eğer; 3. satırdaki ‘CloudTableClient’ sınıfı tüm tablolara, 4. satırdaki ‘CloudTable’ sınıfı ise sadece tek bir tabloya karşılık gelmektedir. 7. satırdaki ‘CloudStorageAccount’ sınıfı ise Azure Storage account’una karşılık gelmektedir. Burada ilgili account ile bağlantı sağlayabilmek için connection string değeri kullanılmaktadır. Bu değeri bulabilmek için portal üzerinden ‘Storage accounts’a gelerek ilgili account’a girdikten sonra ‘Access keys’ sekmesine tıklayınız ve karşınıza gelen ekrandan ‘Connection string’ değerini kopyalayınız.
    Azure Storage Serisi #6 - Azure Table Storage ve Asp.NET Core İle Kullanımı

    Ayrıca 10. satırdaki ‘CreateIfNotExists’ metodu ile ilgili tablo yoksa cloud’da oluşturulmaktadır.

    Bu aşamadan sonra class library inşası tamamlanmıştır. Artık Asp.NET Core uygulamasını geliştirmeye başlayabilirsiniz.

  • Adım 6
    Herhangi bir isimde Asp.NET Core uygulaması oluşturunuz ve ilk olarak yukarıda oluşturulan class library’i ilgili projeye dependency ediniz.
  • Adım 7
    Ardından ilgili class library’de inşa edilen ‘TableStorage’ sınıfını uygulamaya servis olarak ekleyiniz.

        public class Startup
        {
            .
            .
            .
            public void ConfigureServices(IServiceCollection services)
            {
                .
                .
                .
                services.AddSingleton(typeof(INoSQLStorage<>), typeof(TableStorage<>));
                .
                .
                .
            }
    
            .
            .
            .
        }
    
  • Adım 8
    Ve son olarak ‘ProductsController’ isminde bir controller sınıfı oluşturunuz ve içerisini aşağıdaki gibi geliştiriniz.

        [Route("api/[controller]")]
        [ApiController]
        public class ProductsController : ControllerBase
        {
            INoSQLStorage<Product> _noSQLStorage;
            public ProductsController(INoSQLStorage<Product> noSQLStorage)
            {
                _noSQLStorage = noSQLStorage;
            }
            [HttpGet()]
            public IActionResult GetProducts()
            {
                return Ok(_noSQLStorage.All());
            }
            [HttpGet("{rowKey}")]
            public IActionResult GetProduct(string rowKey)
            {
                return Ok(_noSQLStorage.Query(p => p.RowKey == rowKey));
            }
            [HttpPost()]
            public async Task<IActionResult> Create(Product product)
            {
                Product created = await _noSQLStorage.Add(product);
                return Ok(created);
            }
            [HttpDelete()]
            public async Task<IActionResult> Delete(string rowKey, string partitionKey)
            {
                Product deleted = await _noSQLStorage.Delete(rowKey, partitionKey);
                return Ok(deleted);
            }
            [HttpPut]
            public async Task<IActionResult> Update(Product product)
            {
                Product updated = await _noSQLStorage.Update(product);
                return Ok(updated);
            }
        }
    

Tüm bu adımların baştan sona gerçekleştirilmesi neticesinde örnek Azure Table Storage uygulaması geliştirilmiş olacaktır.

Test Edelim
Testimizi Postman aracılığıyla gerçekleştirelim.

POST GET
Azure Storage Serisi #6 - Azure Table Storage ve Asp.NET Core İle Kullanımı Azure Storage Serisi #6 - Azure Table Storage ve Asp.NET Core İle Kullanımı
PUT DELETE
Azure Storage Serisi #6 - Azure Table Storage ve Asp.NET Core İle Kullanımı Azure Storage Serisi #6 - Azure Table Storage ve Asp.NET Core İle Kullanımı

Put operasyonu Timestamp özelliği üzerinden otomatik olarak olası veri tutarsızlığının önlemini almaktadır. Bknz : Entity Framework Core – Data Concurrency Eğer ki, bir tutarsızlık söz konusu olursa aşağıdaki gibi try – catch blokları aracılığıyla ‘StorageException’ türü ile hatayı yakalayıp manipüle edebilirsiniz.

        [HttpPut]
        public async Task<IActionResult> Update(Product product)
        {
            try
            {
                Product updated = await _noSQLStorage.Update(product);
                return Ok(updated);
            }
            catch (StorageException ex)
            {
                if (ex.RequestInformation.HttpStatusCode == (int)HttpStatusCode.PreconditionFailed)
                    return Ok("PreconditionFailed Exception");
                return Ok(ex.Message);
            }
        }

Ya da veri tutarsızlığının göz ardı edilmesini istiyorsanız ‘ETag’ property’sine * değerini verebilirsiniz.

        [HttpPut]
        public async Task<IActionResult> Update(Product product)
        {
            try
            {
                product.ETag = "*";
                Product updated = await _noSQLStorage.Update(product);
                return Ok(updated);
            }
            catch (StorageException ex)
            {
                if (ex.RequestInformation.HttpStatusCode == (int)HttpStatusCode.PreconditionFailed)
                    return Ok("PreconditionFailed Exception");
                return Ok(ex.Message);
            }
        }

Not: Yapılan çalışmaları localde Azure Storage Explorer uygulamasından takip etmek istiyorsanız eğer ‘Microsoft Azure Storage Emulator’ uygulamasının başlat menüsünden çalıştırılmış olması gerekmektedir.
Azure Storage Serisi #6 - Azure Table Storage ve Asp.NET Core İle Kullanımı

Azure Storage Serisi #6 - Azure Table Storage ve Asp.NET Core İle Kullanımı

Microsoft Azure Storage Emulator çalıştırdıktan sonra Console çıktısı…

Tabi Azure Storage Explorer ile localde çalışacaksanız eğer ‘TableStorage’ sınıfında localin connection string değeri tanımlanmış olması gerekiyor. Bunun için, Azure Storage Explorer uygulamasının ‘Explorer’ penceresinde ‘Local&Attached’ -> ‘Storage Accounts’ -> ‘(Emulator – Default Ports) (Key)’ kombinasyonuna tıkladığınızda aşağıdaki ‘Properties’ sekmesine gelen ‘Primary Connection String’ değerini kopyalamanız yeterli olacaktır.
Azure Storage Serisi #6 - Azure Table Storage ve Asp.NET Core İle Kullanımı

Azure Storage Serisi #6 - Azure Table Storage ve Asp.NET Core İle Kullanımı

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Not : Örnek projeyi indirmek için buraya tıklayınız.

Bunlar da hoşunuza gidebilir...

2 Cevaplar

  1. 30 Temmuz 2020

    […] önceki Azure Table Storage ve Asp.NET Core İle Kullanımı başlıklı yazımızda, Table Storage’ı Asp.NET Core ile örneklendirebilmek için bir […]

  2. 30 Temmuz 2020

    […] Azure Storage Serisi #6 – Azure Table Storage ve Asp.NET Core İle Kullanımı […]

Bir cevap yazın

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

*