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 parametreye QueryExpression ya da FetchExpression 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 olarak List<Entity> türündedir ve foreach ya da for 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 da FetchExpression yapılarında birden fazla Entity için JOIN kurgusu oluşturabiliriz. Bunun için LinkEntities 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.

IOrganizationService.RetrieveMultiple metodu
IOrganizationService.RetrieveMultiple metodu

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.

EntityCollection
EntityCollection

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.

IOrganizationService.RetrieveMultiple metodu - ReturnTotalRecordCount
IOrganizationService.RetrieveMultiple metodu – ReturnTotalRecordCount

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.

IOrganizationService.RetrieveMultiple - Sayfalama (Paging) yapısı
IOrganizationService.RetrieveMultiple – Sayfalama (Paging) yapısı

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.

QueryExpression LinkEntity - Inner Join yapısı
QueryExpression LinkEntity – Inner Join yapısı

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.

QueryExpression LinkEntity - AliasedValue

Eğer LinkEntity üzerinden bir değer okumak istersek aşağıdaki gibi bir kod yapısı kullanmalıyız.

AliasedValue 'den data okuma
AliasedValue ‘den data okuma

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 yerine if(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.

You may also like...

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Bu site, istenmeyenleri azaltmak için Akismet kullanıyor. Yorum verilerinizin nasıl işlendiği hakkında daha fazla bilgi edinin.