OData nedir ve nasıl kullanılır sorununa bu makalede cevap bulacağız. OData uzun bir süredir piyada olmasına rağmen Facebook’un GraphQL teknolojisi ile tekrar adı anılmaya başlandı RESTful’a yeni bir boyut kazandıran bu OData teknolojisine girişten başlayıp ortamı nasıl oluşturacağımız ve nasıl kullanabileceğimize kadar örnek kodlarla ilerleyip anlamaya çalışacağız.
OData Nedir? Nasıl Kullanılır?
Odata ile ilgili hızlıca yapmanız gereken testler olduğunda ve bunun için proje oluşturmaya veya odata ortamı oluşturmaya zaman harcamak istemiyorsanız online olarak size sunulan birkaç odata api’si üzerinden istediğiniz testleri yapabileceğiniz http://services.odata.org/ adresine gözatabilirsiniz.
OData Ortamını Hazırlama
Projenize OData’yı eklemek için Nuget’den Microsoft.AspNet.OData kütüphanesini eklemelisiniz fakat OData v4.0 olmasına dikkat ediniz Nuget’de çok fazla v3 kaynak yer almaktadır ve karıştırmanız muhtemeldir. Alttaki görselde hangi kütüphaneyi yükleyeceğiniz noktasında yol gösterici olması adına ekledim.
javascript lower camel case isimlendirme standart’ına uygun olarak property isimlerinin oluşturulmasını istiyorsanız v4 odata kullanmalısınız v4 odata’yı projenize eklemek için odata ortamını hazırlama kısmına tekrar gözatmalısınız.
Metada Görüntüleme
Metadata’yı görüntülemek için http://localhost:65200/odata/$metadata adresine gitmelisiniz bu adres doğru biçimde yazıldığında Tanımladığınız context’ler context’ler altındaki entity’ler ve entity’lere ait özellikler görüntülenecektir.
$filter=(ID eq 1) or (ID eq 2) or (ID eq 3)
ID değeri 1, 2 veya 3 olanları listele diyoruz or yerine and kullanırsak yazdığımız birden fazla filtre koşulunun eşleşmesi durumundaki kayıtlar getirilmesini bekliyor olacağız.
$filter=title ge ‘a’ and title lt ‘n’
title değeri a’dan büyük n’den küçük olanları listele diyoruz.
filterda kullanılabilecek operatörler
Operatör | Açıklama | Örnek |
---|---|---|
Mantıksal Öperatörler | ||
Eq | Eşittir | /Suppliers?$filter=Address/City eq ‘Redmond’ |
Ne | Eşit değildir | /Suppliers?$filter=Address/City ne ‘London’ |
Gt | Büyüktür | /Products?$filter=Price gt 20 |
Ge | Büyük ve eşittir | /Products?$filter=Price ge 10 |
Lt | Küçükse | /Products?$filter=Price lt 20 |
Le | Küçük ve eşittie | /Products?$filter=Price le 100 |
And | Mantıkssal ve | /Products?$filter=Price le 200 and Price gt 3.5 |
Or | Mantıksal veya | /Products?$filter=Price le 3.5 or Price gt 200 |
Not | Mantıksal değilse | /Products?$filter=not endswith(Description,’milk’) |
Matematiksel Operatörler | ||
Add | Ekleme | /Products?$filter=Price add 5 gt 10 |
Sub | Çıkarma | /Products?$filter=Price sub 5 gt 10 |
Mul | Çarpma | /Products?$filter=Price mul 2 gt 2000 |
Div | Bölme | /Products?$filter=Price div 2 gt 4 |
Mod | Mod Alma | /Products?$filter=Price mod 2 eq 0 |
Grup Operatörleri | ||
( ) | Öncelikli Gruplama | /Products?$filter=(Price sub 5) gt 10 |
Kullanılabilecek Hazır Fonksiyonlar
Fonksiyon | Örnek |
---|---|
Metin Fonsksiyonları | |
bool substringof(string po, string p1) | http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=substringof(‘Alfreds’, CompanyName) eq true |
bool endswith(string p0, string p1) | http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=endswith(CompanyName, ‘Futterkiste’) eq true |
bool startswith(string p0, string p1) | http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=startswith(CompanyName, ‘Alfr’) eq true |
int length(string p0) | http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=length(CompanyName) eq 19 |
int indexof(string p0, string p1) | http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=indexof(CompanyName, ‘lfreds’) eq 1 |
string replace(string p0, string find, string replace) | http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=replace(CompanyName, ‘ ‘, ”) eq ‘AlfredsFutterkiste’ |
string substring(string p0, int pos) | http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=substring(CompanyName, 1) eq ‘lfreds Futterkiste’ |
string substring(string p0, int pos, int length) | http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=substring(CompanyName, 1, 2) eq ‘lf’ |
string tolower(string p0) | http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=tolower(CompanyName) eq ‘alfreds futterkiste’ |
string toupper(string p0) | http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=toupper(CompanyName) eq ‘ALFREDS FUTTERKISTE’ |
string trim(string p0) | http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=trim(CompanyName) eq ‘Alfreds Futterkiste’ |
string concat(string p0, string p1) | http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=concat(concat(City, ‘, ‘), Country) eq ‘Berlin, Germany’ |
Tarih Fonksiyonları | |
int day(DateTime p0) | http://services.odata.org/Northwind/Northwind.svc/Employees?$filter=day(BirthDate) eq 8 |
int hour(DateTime p0) | http://services.odata.org/Northwind/Northwind.svc/Employees?$filter=hour(BirthDate) eq 0 |
int minute(DateTime p0) | http://services.odata.org/Northwind/Northwind.svc/Employees?$filter=minute(BirthDate) eq 0 |
int month(DateTime p0) | http://services.odata.org/Northwind/Northwind.svc/Employees?$filter=month(BirthDate) eq 12 |
int second(DateTime p0) | http://services.odata.org/Northwind/Northwind.svc/Employees?$filter=second(BirthDate) eq 0 |
int year(DateTime p0) | http://services.odata.org/Northwind/Northwind.svc/Employees?$filter=year(BirthDate) eq 1948 |
Matematik Fonksiyonları | |
double round(double p0) | http://services.odata.org/Northwind/Northwind.svc/Orders?$filter=round(Freight) eq 32d |
decimal round(decimal p0) | http://services.odata.org/Northwind/Northwind.svc/Orders?$filter=round(Freight) eq 32 |
double floor(double p0) | http://services.odata.org/Northwind/Northwind.svc/Orders?$filter=round(Freight) eq 32d |
decimal floor(decimal p0) | http://services.odata.org/Northwind/Northwind.svc/Orders?$filter=floor(Freight) eq 32 |
double ceiling(double p0) | http://services.odata.org/Northwind/Northwind.svc/Orders?$filter=ceiling(Freight) eq 33d |
decimal ceiling(decimal p0) | http://services.odata.org/Northwind/Northwind.svc/Orders?$filter=floor(Freight) eq 33 |
Tür Fonksiyonları | |
bool IsOf(type p0) | http://services.odata.org/Northwind/Northwind.svc/Orders?$filter=isof(‘NorthwindModel.Order’) |
bool IsOf(expression p0, type p1) | http://services.odata.org/Northwind/Northwind.svc/Orders?$filter=isof(ShipCountry, ‘Edm.String’) |
$count=true
Yazdığınız odata sorgusuna ait dönen kayıt sayısını ayrı bir özellikte almak için kullanmalısınız.
$orderby
Sıralama yapmak için kullanılacak parametredir örnek sözdizimi şöyledir.
$expand=Category
Entity’inizde yer alan virtual ile işaretlenmiş ilişkili diğer sınıflardan değerleride almak için $expand komutunu kullanıyoruz.
$filter=ID eq 5&$expand=SurveyItems
ID değeri 5 olan ve SurveyItems(virtual ile işaretlenmiş ICollection<T> nesnesidir) nesnesini Array türünde döndürür.
$expand=SurveyItem($expand=Survey)
İç içe nesnelerde $expand etme olayında kullanılacak sözdizimidir.
1 | http://localhost:65200/odata/Announce?$orderby=Name asc |
Dikkat edilmesi gereken bazı noktalar
- OData işlemleri için url içerisinde kullanacağınız alan adlarında harf duyarlılığı gözetildiği için entitiy’leriniz içerisindeki özelliklerin adını küçük-büyük harf’e dikkat ederek url içerisine yazınız.
- OData sorgularınızın çalışmasını istediğiniz api metodlarına
EnableQuery
attribute’ünü eklemeyi unutmayın.
“The query specified in the URI is not valid. The property ‘…’ cannot be used in the $select query option.” Hata Çözümü
Bu hatayla OData 5.1.1 sürümünden 6.1.0 sürümüne geçişte yaşadım yükseltme öncesi hiçbir komutta sorun yaşamazken $select, $filter, $top, $take gibi komutlarda birbirine benzer bir hatalar dönmeye başladı ufak bir araştırma ile sorunun güncelleştirme ile gelen global izin verme metodları eklendiğini gördüm bunlarıda alttaki kod satırında göreceğiniz gibi config adındaki HttpConfiguration türüne extension metodlar olarak gelen bu metodları kullanarak izin vermeniz gerekiyor.
1 | config.Filter().Expand().Select().OrderBy().MaxTop(null).Count(); |
Hata oluştuğunda geri dönderilen json türü şu şekildedir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | { "error": { "code": "", "message": "An error has occurred.", "innererror": { "message": "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; odata.metadata=minimal'.", "type": "System.InvalidOperationException", "stacktrace": "", "internalexception": { "message": "No connection string named 'MySampleDb' could be found in the application config file.", "type": "System.InvalidOperationException", "stacktrace": " at System.Data.Entity.Internal.LazyInternalConnection.get_ConnectionHasModel()\r\n at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()\r\n at System.Data.Entity.Internal.InternalContext.Initialize()\r\n at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)\r\n at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()\r\n at System.Data.Entity.Internal.Linq.InternalSet`1.GetEnumerator()\r\n at System.Data.Entity.Infrastructure.DbQuery`1.System.Collections.IEnumerable.GetEnumerator()\r\n at System.Web.OData.Formatter.Serialization.ODataResourceSetSerializer.WriteResourceSet(IEnumerable enumerable, IEdmTypeReference resourceSetType, ODataWriter writer, ODataSerializerContext writeContext)\r\n at System.Web.OData.Formatter.Serialization.ODataResourceSetSerializer.WriteObjectInline(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext)\r\n at System.Web.OData.Formatter.Serialization.ODataResourceSetSerializer.WriteObject(Object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)\r\n at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)\r\n at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()" } } } } |
OData ile ilgili çok geniş yelpazeli official örneklere https://github.com/OData/ODataSamples repo’sundan ulaşabilirsiniz.
✍ Lütfen OData Nedir? makalesi için olumlu-olumsuz tüm görüşlerinizi bana yorum yada mail yolu ile iletmeyi ihmal etmeyin.
🔗 Sosyal medya kanallarından OData Nedir? makalesini paylaşarak destek olursanız çok sevinirim.
👋 Bir sonraki makalede görüşmek dileğiyle.