IOrganizationService RetrieveMultiple Metodu
Bu yazı 27 Mayıs 2019 tarihinde Medium/@dynamics365 altında yayınlanmıştır. 21 Mayıs 2020 tarihinde emregulcan.com altında taşınmıştır.
Merhaba,
Bu yazıda Dynamics 365 CE (CRM) SDK ‘da IOrganizationService
interface ‘in sağlamış olduğu RetrieveMultiple
metodunu inceleyeceğiz.
RetrieveMultiple
metodu, Dynamics 365 CE (CRM) ‘de bir varlık üzerinde bulunan kayıtların tümünü ya da belirli bir kritere göre uygun olanları listelememizi sağlar.
Sayfalama (Paging
) , birden fazla ilişkili Entity üzerinde JOIN
ve sıralama (Order
) gibi imkanları bulunmaktadır. SQL ‘de SELECT
sorgusu ile aynı işlemi yapmaktadır.
Önemli Noktalar
- RetrieveMultiple metodu sadece 1 parametre alır.
QueryBase
türünde olan bu parametreyeQueryExpression
ya daFetchExpression
türünde sorgu yapılarını gönderebiliriz. - RetrieveMultiple metodunun geri dönüş türü
EntityCollection
‘dur. Bu özel nesne ilgili sonuç kümesi için gerekli olan bütün bilgileri içermektedir. Sorgumuza uygun kayıtları EntityCollection nesnesinin Entities property ‘inden okuyabiliriz, basit olarakList<Entity>
türündedir veforeach
ya dafor
döngüsü ile bu property içinde dönerek kayıtlarımızı okuyabiliriz. - Daha önce
Retrieve
metodunda anlatmış olduğum Entity Attributes ‘de sadece Dynamics 365 CE (CRM) ‘de dolu olan alanların bulunması ve Field Level Security aynı şekilde RetrieveMultiple için de geçerlidir. Burada dikkat etmeniz gereken önemli bir nokta, X alanı sonuç kümesinde bir kayıtta varken, diğerinde bulunmayabilir. - RetrieveMultiple metodunda kullanacağımız
QueryExpression
ya daFetchExpression
yapılarında birden fazla Entity için JOIN kurgusu oluşturabiliriz. Bunun içinLinkEntities
kullanmalıyız. - RetrieveMultiple ile yapılan sorgulamalarda sayfa başına listelenecek kayıt sayısı varsayılan olarak 5000 ‘dir. Dynamics 365 CE (CRM) sorgu çalıştırıldığında TOP 5001 olarak sorgulama yapar ve eğer 5000+ kayıt dönerse bir sonraki sayfanın olduğu bilgisini bize iletir. Bu nedenle QueryBase kriterlerinizde 5000 adetten fazla kayıt ile çalışma durumunuz olursa Paging (Sayfalama) yapmanız gerekecektir.
.NET Projesi – Örnek Kod
.NET projelerimizde Microsoft.CrmSdk.CoreAssemblies
kütüphanelerini ekleyerek Dynamics 365 CE (CRM) ‘de RetrievMultiple metodunu kullanabiliriz. Bu kütüphaneleri NuGet üzerinden projemize dahil edebiliriz.
Dynamics 365 CE (CRM) SDK kütüphanelerini projemize nasıl ekleyeceğimizi daha önce burada detaylı olarak anlatmıştım.
QueryExpression
kullanarak RetrieveMultiple metodu ile işlem yapmak en basit haliyle aşağıdaki gibidir.
Bu QueryExpression
sorgusunun SQL karşılığı SELECT * FROM dbo.Contact
‘dır.
ColumnSet
‘de istersek sadece ihtiyacımız olan alanları belirleyebiliriz, bu şekilde sorgu performansımızı arttırmış oluruz. Eğer herhangi bir tanımlama yapmazsak varsayılan olarak sadece ilgili Entity (Varlık) ‘in Primary Key bilgisini (Örnek : contactid) listeleyecektir.
data değişkenini yakından incelersek (Visual Studio ‘da QuickWatch yaparak bakabilirsiniz) aşağıdaki gibi bir çıktı göreceksiniz. Bizim için önemli olan property Entities
, ayrıca diğer alanlar, binlerce kayıtta çalışırken yardımcı olan bir çok bilgi içermekte.
Dikkat ederseniz TotalRecordCount
-1 döndü, bu hata değil, QueryExpression ‘da bunun ilgili olarak gerekli düzenlemeleri yapmadığımız için değer dönmedi. Sorgumuzu aşağıdaki şekilde güncelleyerek bu bilgiye erişebiliriz.
Database ‘den RetrieveMultiple ile aldığımız kayıtları aşağıdaki gibi basit bir döngü içinde okuyabiliriz. Ben önlem olarak NULL kontrolü ve Count kontrolü yaparak döngüye giriyorum.
foreach döngüsü ilgili Array / List ‘de kayıt yoksa zaten hiç çalışmayacaktır, fakat her ihtimale karşı kontrol ekliyorum.
Normal şartlarda EntityCollection ve EntityCollection.Entities hiç bir zaman NULL olmaz, fakat söz konusu Dynamics 365 CE (CRM) olduğunda, SDK ‘da yapılan hatalı bir güncelleme sonrasında bu nesnenin NULL dönmeyeceğini garanti edemezsiniz.
Benim her zaman söylediğim birşey vardır, asla data ‘ya güvenme, database ‘e sen eklesen bile!, söz konusu Dynamics 365 CE (CRM) ve servisleri olduğunda bunu x2 olarak düşünebiliriz. Belki biraz paranoyak bir düşünce olabilir fakat, Dynamics 365 CE (CRM) ‘de son 10 yılda yaşadığım sorunları düşündüğümde haklı çıktığım noktalar var 🙂
Sayfalama (Paging)
Yukarıda bahsettiğim gibi Dynamics 365 CE (CRM) ‘de sayfa başına listeleyebileceğimiz kayıt sayısı 5000 ‘dir. Dolayısıyla 5000 ‘den fazla kayıt içeren data setlerinde çalışırken sayfalama ihtiyacımız olacaktır.
Dynamics 365 CE (CRM) ‘de Primary Key bilgisi GUID (uniqueidentifier) olduğu için sıralama işleminde WHERE primarkey > X AND primarykey < Y
gibi bir kriter ekleyemiyoruz.
Fakat Dynamics 365 CE (CRM) RetrieveMultiple yapısında bu iş için bize bir takım kolaylıklar sağlamakta ve sayfalama işini bizim yerimize kendisi yönetmekte. Biz sadece sonuç olarak dönen EntityCollection ‘da MoreRecords
ve PagingCookie
değerlerini kontrol edip, QueryExpression ‘da PageInfo
property ‘de gerekli alanları bu değerler ile düzenleyip yeniden sorgulama yaparak tüm kayıt seti içinde sayfa sayfa dolaşabiliriz.
İstersek direkt olarak belirli bir sayfaya gidip, o sayfada bulunan kayıtları da listeleme imkanımız bulunmakta.
Bunun için C# ‘da do{business logic…}while(condition)
döngüsünü kullanarak, EntityCollection.MoreRecords
değeri true
olduğu sürece sürekli olarak sorgu yapabiliriz.
Neden do{business logic…}while(condition)
döngüsünü kullandığımı açıklamak gerekirse, biraz yazılımın temellerine inmemiz gerekir. Bu döngüde uygulama çalıştığında her durumda do{business logic…}
kodlarımız çalışacaktır, sonrasında while(condition)
doğrulaması yapılacak ve eğer şartlar sağlanıyorsa (true) do{business logic…}
tekrar tekrar çalışmaya devam edecektir.
Yukarıdaki örnekte QueryExpression ‘da PageInfo property ‘de Count=1 ve PageNumber=1 olarak değer atadık.
Burada Count her sayfada listelenecek kayıt sayısını belirtmekte, elbette gerçek hayatta kayıtları birer birer listelemek çok mantıklı olmayacaktır, bunun yerine siz kendi senaryonuza uygun bir sayı belirleyebilirsiniz.
PageNumber
değeri ise sorgunun hangi sayfa için geçerli olacağını belirtmektedir, uygulama ilk kez çalıştığında 1. sayfada bulunan kayıtları listelemek muhtemelen mantıklı bir işlem olacaktır.
Uygulama ilk çalıştığında do{business logic…}
yapısı çalışacak ve data = organizationService.RetrieveMultiple(query);
ile ilk sorgulamamızı yapacaktır.
Eğer dönen sonuçta MoreRecords true
ise while(condition)
sağlanmış olup, tekrar do{business logic…}
tetiklenecektir.
Burada dikkat edilmesi gereken nokta do{business logic…} içinde yapmış olduğumuz QueryExpression güncellemesi.
query.PageInfo.PageNumber++;
ile bir sonraki sorgulama sayfasını, query.PageInfo.PagingCookie=data.PagingCookie;
ile mevcut datanın sayfalama bilgilerini belirtiyoruz.
Dynamics 365 CE (CRM) ‘de bulunan Contact kayıtlarım ve örnek kodun listelediği kayıtları aşağıdaki ekran görüntüsünde inceleyebilirsiniz.
Entity ‘ler Arasında JOIN İşlemi ve LinkEntity Yapısı
Daha önce bahsettiğim gibi RetrieveMultiple birden fazla Entity için JOIN imkanı sunmakta, bunun için QueryExpression ‘da LinkEntity
isimli özel bir nesne kullanmaktayız ve bunu LinkEntities isimli bir Collection property ‘e değer olarak atamaktayız.
LinkEntity ‘de kullanmış olduğunuz JoinOperator
parametresine göre SQL karşılığı INNER JOIN
ya da LEFT JOIN
‘dir.
Yukarıdaki örnekte contact ve account Entity ‘lerini parentcustomerid
ve accountid
alanları üzerinden JoinOperator.Inner
parametresi ile Inner Join
ile birbirine bağlayarak sorgulama yaptım.
Bu sorgunun SQL karşılığı SELECT * FROM dbo.Contact c INNER JOIN dbo.Account acc ON c.parentcustomerid=acc.accountid
LinkEntity kullandığımızda sonuç kümemizde ufak farklılıkla oluşturmaktadır. Aşağıdaki ekran görüntüsünde görebileceğiniz üzere account Entity için listelenen tüm alanlar AliasedValue<T>
türünde bir wrapper nesne içinde yer almakta.
Örnekte accountratingcode
attribute OptionSetValue
türünde bir data içermekte, fakat Account üzerinden alındığı için AliasedValue<OptionSetValue>
olmakta. Ayrıca ilgili alanın ismi LinkEntity ‘de vermiş olduğumuz EntityAlias değeri ile listelenmekte ve acc.accountratingcode
olmakta.
Eğer LinkEntity üzerinden bir değer okumak istersek aşağıdaki gibi bir kod yapısı kullanmalıyız.
Burada dikkat etmemiz gereken noktalar;
- LinkEntity ‘den gelen data ‘nın tüm attribute ‘lerinde EntityAlias ‘da belirttiğimiz değer prefix olarak yer alır (örnek : acc.xxxxx)
- LinkEntity ‘den gelen data ‘yı
GetAttribute<AliasedValue>("attributename")
yapısı ile okuyarak, varsa data, yoksa NULL dönmesini sağlayabiliriz (bunun yerineif(item.Contains("attributename"))
da kullanabilirsiniz) - AliasedValue olarak aldığımız değerin Dynamics 365 CE (CRM) ‘de ki data tipine göre
AliasedValue.Value
değerini ilgili tipe dönüştürmemiz gerekmekte.
Umarım faydalı bir yazı olmuştur.
IOrganizationService metotları için oluşturduğum Index yazısına buradan ulaşabilirsiniz.
Dynamics 365 CE (CRM) SDK konusunda ilgili tüm yazılara tek nokta üzerinden ulaşmak isterseniz http://www.emregulcan.com/dynamics365-sdk adresine bakabilirsiniz.