Open Data Protocol — ODATA

Cihat Solak
lTunes Tribe
Published in
4 min readMar 11, 2021
Open Data Protocol

Aramızdan birileri sanki RESTful API’leri tüketen en iyi uygulamaları soruyor olabilir mi? 👀 Sormuyorsa da ben söyleyeyim; en iyi uygulamalardan biri Microsoft’un 2007 yılında adımlarını attığı ODATA(Open Data Protocol).

Peki… Peki… ODATA kelimesini belki de birçok yerde gördük. Bir halk kahramanı ♛ çıksın ve bu OData nedir? Anlatsın derken işte OData budur;

Veri kaynaklarını url üzerinden sorgulamak için kullanılan REST ve HTTP tabanlı protokoldür. Ayrıca Web API projelerinde kullanılmaktadır. ODATA URI yapısını kullanarak veri tabanına ışık hızında ‍🚀 sorgu gönderebilir, temel ekle/sil/güncelle operasyonlarını da yapabiliriz.

Kafada hiç soru işareti oluşmasın ben OData konusunu LTunes Talks da da anlattım, şimdi konu anlatımlı kitaptan çalışıp, içeriğin sonunda bırakacağım github linki ile soru çözümü yaptığımızda bence sorun kalmayacak. 👨🏻‍🏫

Ne işe yarar bu OData?

Web API üzerinden elde ettiğimiz veriyi özelleştirebilmemizi ya da farklı formatlarda sağlayabilmemiz için birden fazla endpoint geliştirme ihtiyacımızı ortadan kaldırabilecek bir yapıdır. [ GetAll() / GetEntityById() / GetEntityByName()]

Böylece client biraz kolları sıvayacak, 🔫 back-end ise karmaşık ya da özel endpointler geliştirme maliyetinden kurtulacak. Kulağa hoş geliyor gibi.

Avantajlar 🎯

Http tabanlı bir servis olduğu için veri üzerindeki sorguları url üzerinden yapar, çok basit bir şekilde sınırlamalarda getirebiliriz.

Filtreli veriler çekeceğimiz için performans olarak avantajlı duruma geçeriz.

Veri modellerimize çok hızlı bir şekilde servis oluşturabiliriz.

Projeye Nasıl Dahil Edilir?

Startup.cs
  1. Paket yöneticisi üzerinden “Microsoft.AspNetCore.OData” kurulumu yapılır.
  2. ConfigureServices katmanına services.AddOData() eklemesi yapılır.
  3. Middleware(ara uygulama) olarak Configure içerisinde basit birkaç ayarlama yapılır.
  4. UseEndpoint içerisinde route tanımı yapılır.

Performans 🧨

OData’yı implement ettiğimiz web api projelerimizde yazmış olduğumuz actionlarda IQueryable<T> interfacesi dönmeye özen göstermemiz gerekmektedir. Çünkü eğer IQueryable interfacesini dönerseniz bu şu anlama geliyor, herhangi bir client url üzerinde bir filtreleme işlemi gerçekleştirdiği zaman OData oradaki filtreyi alıp birebir sql sorgusuna dönüştürüyor. ♻️

IEnumerable vs IQueryable

Eğer IQueryable<T> yerine IEnumerable<T> dönersiniz EntityFramework gidip önce tüm veriyi alır ve bellekte tutar ve daha sonra almış olduğu (örneğin 100.000 adet) kayıt üzerinden sorgu atar. Bu da bize çok ciddi bir performans kaybı🐢 sağlar.

Microsoft SQL Server Profiler

Görsel de anlatılmak istenen sorgular arasında ki detay farkı aslında görüntüleyebiliriz.

Buradaki performans mantığını daha iyi anlayabilmek için SQL Server Profiler aracılığıyla bir trace oluşturup ✔️ yaptığınız tüm işlemlerin MSSQL tarafına ne şekilde yansıdığını takip edebilirsiniz.

METADATA ($metadata)

ODatanın kullandığı tüm entityler hakkında bilgi içeren dökümandır. Bu bir nevi swagger’a benzemektedir. 📃 Örneğin “ www.ltunes.com.tr/odata/$metadatasorgusu ile OData ile ilişkili tüm classlarımızın property, navigation property veya primary key gibi özelliklerini görüntüleyebiliriz. Ayrıca Odata bize her sorgu sonucunda ilgili metadata url’ini de dönmektedir.

QUERY OPTİONS

Server üzerinden dönecek data miktarını ⚖️ ya da özelleştirilmiş yani ihtiyacımız olan datayı kontrol etmek için kullandığımız seçeneklerdir. Query options kullandığımızda dönen data her zaman iki parçadan oluşmaktadır.

OData — Query Options

1- Resource((at)odata-context): Metedata 💡 bilgilerini içeren bilgi döner.

2- Value[]: Response bilgisinin döndüğü kısımdır ve tek bir değer almaya çalışsak dahi (GetProductById) value daima array olarak bizlere dönüş sağlar.

Sorgulama olarak $select, $expand, $orderby, $top, $count, $skip, $filter gibi aslında veri tabanın sorgularından aşina olduğumuz komutlar kullanmaktadır. Burada expand ve filter ifadelerini açıklamak gerekirse;

$Expand : Sorgulama yaptığımız entity’nin navigation property’si varsa o entity’nin de datalarını almamıza olanak sağlar. Örneğin ürünleri listelerken o ürünün bağlı bulunduğu kategorilerine de ihtiyaç duyabiliriz.

$Filter: Filtremele yapmak için kullanırız. Mantıksal işlemler, aritmetik işlemler ➕ ➖ ➗ ✖️ ve fonksiyonları kapsamaktadır.

Oops! Query Options yazarken string key 🔑 ve value şeklinde olduğu için resource sonrasında soru işareti (?) ve sonrasında dolar($) 💰 işaretini kullanmamız gerekmektedir. Birden fazla filtreleme yapmayı da düşünüyorsak bunları ampersand(&) işareti ile birleştirmeyi de unutmamalıyız.

https://ltunes.com.tr/odata/Categories?$count=true&$expand=Products($count=true)

[EnableQuery] ve OData Pagination 📚

EnableQuery attribute’u ile servis adreslerimize sorgulama yeteneği kazandırıyoruz. Ayrıca belirli özellikleri sağlayarak hızlı ve basit bir şekilde sayfalama da yapabiliriz.

EnableQuery Attribute

Sayfalama özelliği kazandırdığımız servis adreslerine yaptığımız sorgu sonucunda response’da OData tarafından her zaman bizlere ((at)odata-nextLink) adında bir link 📎 dönmektedir. Bu da bizim bir sonraki sayfaya ilerlemizi sağlar. Bir düşünce aslında bu özellik bana mobil tarafta 📱 ya da single page applicationlarda kullanılan Infinite Scrool mantığını çağrıştırmaktadır.

Custom Action/Function ve Unbound Action/Function

Custom Action/Function adından da anlaşılacağı üzere bizlere özelleştirebileceğimiz servis adresleri konusunda yardımcı olmaktadır. Best Practices olarak action http post isteklerinde, function ise http get isteklerinde kullanılmaktadır.

Bir method içinde karmaşık tip ya da birden fazla parametre almasını istiyorsak customize etmemiz gerekmektedir.

Unbound (Entity Bağımsız) Fonksiyon

Unbound ifadesi ise customdan farklı olarak tamamen entity bağımsız bir servis adresini işaret etmektedir. Burada basit bir örnek vermem gerekirse kdv hesaplayan bir servis adresi düşünebiliriz. Bu yazmış olduğumuz servisi tabiki startup’da bulunan configure içerisinde de tanımlamasını yapıyoruz.

Bu kadar teori kısmı bence yeterli. Yapılması gerekenin github dan projeyi klonlayıp servis adreslerini postmanden test etmek olduğunu düşünüyorum. Şimdilik benden bu kadar. 👋🏼

Wir Sehen Uns 😎

--

--