Xrm.Sdk.Messages.ExecuteMultipleRequest

Merhaba,

Bu yazıda Dynamics 365 CE (CRM) SDK ‘da Microsoft.Xrm.Sdk.Messages namespace altında yer alan ExecuteMultipleRequest mesajını detaylı olarak inceleyeceğiz.

ExecuteMultipleRequest, Dynamics 365 CE üzerinde tek bir seferde birden fazla işlem (bulk operation) yapmamıza imkan sağlayan bir yapıdır.

Genel olarak, Dynamics 365 sistemine data aktarımı (migration / integration) gibi performans gerektiren işlemlerde kullanmaktayız, fakat bulk işlem yapmak istediğiniz herhangi bir aşamada kullanabiliriz. Toplu işlemlerde (bulk operation) client – server arasında network akışını (round trip) en aza indirmek amacıyla Dynamics 365 CE (CRM) SDK ‘a eklenmiştir.

Internette kolayca bulabildiğiniz örneklerin aksine sadece Create, Update, Delete gibi operasyonlar ile değil, aynı zamanda RetrieveMultipleRequest gibi data okuma amaçlı işlemler için de kullanılmaktadır. Requests parametresi OrganizationRequest ‘den türetilmiş bütün Dynamics 365 SDK mesajlarını kabul etmektedir, fakat bu konuda ufak bir istisna bulunmaktadır, detayları limitasyonlar başlığında detaylı olarak anlatacağım.


ExecuteMultipleRequest Nasıl Çalışır?

.NET tarafında kod örneklerine geçmeden önce ExecuteMultipleRequest ‘in çalışma mantığından bahsetmekte fayda var. Yukarıda bahsettiğim gibi OrganizationRequest ‘den türetilmiş bütün Dynamics 365 SDK mesajlarını kabul eden ve collection (list) olarak data alan Requests parametresi bulunmaktadır. Bu sayede limitasyonlar dahilinde istediğimiz kadar request bilgisini bu listeye ekleyebiliriz.

Settings parametresi ise ExecuteMultipleSettings tipinde bir değer almaktadır. Bu parametre sayesinde ilgili işlemin çalışma zamanında (run-time) nasıl tepki vereceğini istediğimiz gibi belirleyebiliyoruz.

ExecuteMultipleRequest ‘in dönüş tipi ExecuteMultipleResponse ‘dir. Mevcut işlem için detayları içeren IsFaulted ve Results isimli 2 parametresi mevcuttur.

ExecuteMultipleRequest, paket içinde bulunan herhangi bir işlemde hata meydana geldiğinde exception oluşturmaz, bunun yerine IsFaulted değeri TRUE olarak döner ve Results içinde hatalı kaydın bilgisi yer alır.

İşlem sonrasında oluşan cevaplar ise Results parametresi içinde yer almaktadır. Settings parametresinde vermiş olduğumuz ayarlara göre bu parametrenin dönüş değerlerini içerip içermemesi değişkenlik göstermektedir.

Unutmamamız gereken önemli bir nokta, IsFaulted değeri TRUE olduğunda, Settings parametresinde vermiş olduğumuz değerlerden bağımsız olarak Responses parametresi mutlaka hatalı kayıtları içerir.

ExecuteMultipleRequest ‘i çalıştırabilmek için IOrganizationService interface ‘in Execute metodunu kullanmaktayız.

ExecuteMultipleRequest, OrganizationService oluşturduğumuz (ya da Impersonate yaptığımız) kullanıcının context bilgisi ile işlem yapar, dolayısıyla Requests parametresi içinde yer alan tüm işlemler bu kullanıcının yetkisine göre çalıştırılacaktır. CreatedBy , ModifiedBy gibi alanlar bu kullanıcı bilgisini içerecektir. Eğer herhangi bir işlem için yetkisi yoksa ilgili işlem için hata oluşacaktır.


ExecuteMultipleSettings

ContinueOnError ve ReturnResponses isimli boolean (True / False) değer alan 2 parametreye sahip olan bu yapı ile ExecuteMultipleRequest ‘in çalışma zamanında nasıl davranacağını belirlemekteyiz.

ReturnResponses parametresi, paket içinde yer alan request (OrganizationRequest) ‘ler için response bilgilerinin (OrganizationResponse) dönmesini sağlar. Eğer Requests içinde CreateRequest işlemleri varsa ve oluşan kayıtların Id bilgilerini alıp başka bir sisteme kaydetmek ya da log olarak yazmak istiyorsak bu parametreye TRUE değer vermeliyiz.

Bazı kaynaklarda ReturnResponses bilgisinin TRUE olarak atanması performans kaybı oluşturduğu yönünde yorumlar bulunmakta, açıkcası ben böyle bir test yapmadım. Elbette işlem sonuçlarına ihtiyacımız yoksa ya da operasyonel anlamda herhangi bir bilgi içermeyen (UpdateRequestUpdateResponse gibi) isteklerimiz varsa bu bilgiyi TRUE olarak ayarlamak zaten gereksiz bir durum. Bu nedenle ihtiyacınıza en uygun şekilde değer atamanız mantıklı olacaktır.

ContinueOnError parametresi, herhangi bir hata anında işlemin devam edip etmeyeceği bilgisini düzenlemektedir. TRUE gönderdiğimizde paket içinde yer alan işlemlerde herhangi bir hata meydana geldiğinde sıradaki işlem ile devam etmesini sağlarız. Bu sayede tüm paket bitinceye kadar işlemler devam eder. Eğer FALSE olarak değer atarsak paketin içinde oluşan ilk hata sonrasında işlem kesilir ve o ana kadar yapılmış tüm işlemler için cevap döner, hatalı kaydın sonrasında listede yer alan işlemler devam etmez.

ExecuteMultipleRequest ‘te yer alan her bir işlem kendi transaction yapısında işlenir. Herhangi bir hata olması durumunda sadece ilgili kayıt bazında rollback işlemi gerçekleşir. Hatalı kayıt öncesinde yapılan işlemlerde herhangi bir değişiklik, rollback işlemi söz konusu değildir.


Run-time Limitleri

ExecuteMultipleRequest hem kendini ve hem de platformu korumak için belirli kısıtlamalar içermekte. Bu limitleri bilmek ve dikkate almak yazdığımız uygulamanın sorunsuz ve performanslı olarak çalışmasını sağlayacaktır.

Paket Kısıtlaması (MaxBatchSize)

İlk kısıtlama Requests parametresine ekleyeceğimiz istek sayısı ile ilgili. ExecuteMultipleRequest ile tek seferde en fazla 1000 istek içeren bir paket gönderebiliriz.

Eğer paketimiz 1000+ istek içeriyorsa, IOrganizationService.Execute metodunu çalıştırdığımızda -2147220715 (Not Supported) hata kodu ile “ExecuteMultiple Request batch size exceeds the maximum batch size allowed!” hatası oluşacaktır. Oluşan hatanın paket sayısından kaynaklı olduğunu tespit etmek için dönen hata mesajını kontrol edebilir ya da hata detayında MaxBatchSize anahtar kelimesini arayabiliriz. Bu hatayı detaylı olarak Hata Yönetimi başlığında inceleyeceğiz.

Elbette bu hatayı çok kolay bir yöntemle engelleyebiliriz. Elimizde bulunan istekleri 1000 ‘lik ya da daha düşük request bilgisi içerecek şekilde paketler halinde bölüp işlem yapabiliriz. Bunun için aşağıdaki gibi bir kod yapısı kullanabilirsiniz.

Kodda yer alan itemPerPackage, ExecuteMultipleRequest paketimizde her döngü için gönderilecek Request sayısını belirlemektedir. Örnek kodda 150 request olarak belirledim.

ExecuteMultipleRequest - Paket Hazırlama
ExecuteMultipleRequest – Paket Hazırlama


Recursion Kısıtlaması

Yazıya başlarken ExecuteMultipleRequest ‘in OrganizationRequest ‘ten türetilmiş tüm istekleri çalıştırabildiğinden bahsetmiştim. Bu konuda bir istisna bulunmakta.

Bir ExecuteMultipleRequest isteği içinde başka bir ExecuteMultipleRequest kullanamayız. Böyle bir işlem yaptığımızda yine exception oluşacaktır. Fakat bu durumda hatayı yakalamak ve tespit etmek için try-catch(FaultException<OrganizationServiceFault> fault){ } bloğu yerine ExecuteMultipleResponse ‘in IsFaulted parametresi TRUE olacaktır ve hata ilgili request için dönecektir.


Platform ve API Kısıtlamaları

Direkt olarak ExecuteMultipleRequest ile ilgili olmasa bile bizim işlerimizi etkileyebilecek diğer hatalar için platform API limitlerinin detaylı olarak yer aldığı dokümantasyona bakmanızı öneririm. Bu hatalardan biri oluştuğunda uygulama direkt olarak hata oluşturur, eğer uygulamamızda try-catch varsa catch(FaultException<OrganizationServiceFault> fault){ } bloğu ile oluşan hatanın detayını yakalayabiliriz.

Plug-in ya da Workflow Assembly ‘lerde ExecuteMultipleRequest Kullanımı

Microsoft, custom plug-in ya da workflow assembly ‘ler içinde işlem yaparken ExecuteMultipleRequest kullanmamızı öneriyor. Bunun yerine bu tarz işlemlerde bir döngü içinde işlem yapmamız daha sağlıklı olacaktır.

Detaylar için https://docs.microsoft.com/en-us/powerapps/developer/data-platform/best-practices/business-logic/avoid-batch-requests-plugin adresine bakabilirsiniz.


ExecuteMultipleRequest Hata Yönetimi

Uygulamamızda herhangi bir kural ihlali yoksa ya da akışımız ile ilgili olarak farklı bir hata mevcut değilse ExecuteMultipleRequest kullanımında herhangi bir exception fırlatılmaz, diğer bir değişle try-catch ‘e normal şartlar altında ihtiyaç duyulmaz. Hata yönetimi ExecuteMultipleResponse ‘in IsFaulted parametresi kontrol edilerek yapılmaktadır. Bu parametre TRUE dönüyorsa işlemlerin birinde ya da birkaçında hata meydana gelmiştir. FALSE ise tüm işlemler başarılı bir şekilde tamamlanmış demektir.

Limitasyonlar başlığı altında yer alan kısıtlamaların ihlal edilmesi ihtimaline karşı kodumuzun içinde try-catch (FaultException<OrganizationServiceFault> fault) bloğu kullanmakta fayda var.

Aşağıdaki örnek kod yapısını kullanarak ExecuteMultipleRequest yapısında hataları yakalayabilir ve hatalı kayıtları kolayca tespit edebilirsiniz. Bu kod genel olarak bir exception oluşmadığı zaman kullanabileceğimiz yapıdır.

ExecuteMultipleRequest - Hatalı Kayıtları Bulma
ExecuteMultipleRequest – Hatalı Kayıtları Bulma

Limitasyonlar ya da farklı bir hata nedeniyle oluşan hataları yakalamak için aşağıdaki gibi bir try-catch yapısı kullanabilirsiniz. Örnek kodda MaxBatchSize hatasını tespit edebilmek için Microsoft ‘un önerdiği şekilde hata detayı içinde MaxBatchSize anahtar kelimesini arayarak hem hata tespiti yapıyoruz hem de ilgili Instance (Organization) için geçerli olan MaxBatchSize değerini elde ediyoruz.

ExecuteMultipleRequest - Hata Yakalama
ExecuteMultipleRequest – Hata Yakalama

.NET Projesi – Örnek Kod

Öncelikli olarak projemize Microsoft.CrmSdk.CoreAssemblies kütüphanelerini eklememiz gerekiyor. Eğer bu konu hakkında bilginiz yoksa daha önce hazırlamış olduğum detaylı yazıya göz atmanızda fayda var.


PL-400 Microsoft Power Platform Developer Sorusu (Bonus ;))

Geçtiğimiz günlerde PL-400 Microsoft Power Platform Developer (eski adı MB-400 Power Apps + Dynamics 365 Developer) sertifikası için sınava girdim. Sınavda aşağıdaki gibi bir soru ile karşılaştım, ayrıca bir çok arkadaşımdan benzer konu ile ilgili soru aldığım için örnek soruyu bu yazıya dahil etmek istedim.

PL-400 ExecuteMultipleRequest Sorusu
PL-400 ExecuteMultipleRequest Sorusu

PL-400 ExecuteMultipleRequest Sorusu
PL-400 ExecuteMultipleRequest Sorusu

Bu soru için dikkat etmemiz gereken en önemli nokta Settings (ExecuteMultipleSettings) parametreleri.

  • ContinueOnError parametresi TRUE, yani liste içinde herhangi bir hata olsa bir bir sonraki işlem ile devam edecek
  • ReturnResponses parametresi FALSE, bu durumda ExecuteMultipleRequest içinde yer alan işlemler için (CreateRequest, UpdateRequest vb) herhangi bir sonuç dönmeyecek.

Bu bilgiler doğrultusunda cevaplar aşağıdaki gibi olacaktır;

The developer is able to get to the newly created accounts IDs

Developer, yeni oluşturulan kayıtların ID bilgilerini alabilir

Cevap HAYIR. ReturnResponses = false olduğu için işlem bilgileri dönmeyecektir. Bu durumda yeni kayıtların ID bilgilerini elde edemeyiz.

If an error occurs, the developer can get access to the request that caused the fault

Eğer hata olursa Developer hatalı kayda erişebilir

Cevap EVET. ReturnResponses parametresine bakılmadan, hatalı kayıtlar her durumda response içinde yer alır.

If there are errors in the request, the request will raise an exception at the first error and stop processing

Eğer hata meydana gelirse, ilk hatada exception fırlatılır ve işlem durdurulur

Cevap HAYIR. ContinueOnError = true olduğu için işlemlerde hata oluşsa bile bir sonraki işlem ile devam eder

If there are ten errors in the 1000 CreateRequest requests, ten responses will be returned from the platform

Eğer 1000’lik pakette 10 hatalı işlem varsa, platformdan 10 cevap döner

Cevap EVET. İkinci soru ile benzer şekilde, hatalı kayıtlar her durumda response içinde yer alır. Bu durumda eğer 1000 istek içinde 10 adet hatalı kayıt mevcutsa response içinde bu hatalı kayıtları görürüz.


Kişisel Deneyimlerim ve Önemli Noktalar

Uzun bir yazının sonuna gelirken ExecuteMultipleRequest yapısı ile ilgili bugüne kadar deneyimlediğim bazı önemli bilgileri de sizinle paylaşmak istiyorum.

1. İsteklerin (OrganizationRequest) Requests parametresine eklenme sırası

ExecuteMultipleSettings ReturnResponses parametresini TRUE olarak atamışsak, ExecuteMultipleRequest işlemi tamamlandığında, Requests parametresi içinde yer alan her bir item için ExecuteMultipleResponse aynı sırada (Index) bir response (OrganizationResponse) ya da hata (Fault) datası içerir. Bu sayede başarılı ya da hatalı işlemler için bir akış planlayabiliriz.

Eğer yüksek data hacimleriyle çalışıyorsak ve uygulamamızda performans kazanmak için Requests içine eklenecek işlemleri Parallel.Foreach ya da Parallel.For ile eklemişsek ve eklediğimiz sırayı takip etmediysek, maalesef response datasını okumamız ve hangi item için hangi response döndü tespit etmemiz zorlaşacaktır.

Bu nedenle ek bir kontrol mekanizması vb. oluşturmak yerine isteklerimizi normal şekilde for / foreach döngüsünde eklersek response ‘lar üzerinde çalışmamız daha kolay olacaktır.

2. Tek bir istekte gönderilecek olan request sayısı

Normal şartlar altında tek bir istek ile 1000 request ‘lik bir paket gönderip işlem yapabiliyoruz. Fakat bu sayı güçlü sunucular ve arka planda senkron plug-in ya da workflow olmayan durumlar için geçerli diyebiliriz.

Eğer herhangi bir işlem için arka planda farklı akışlarınız mevcutsa işlemler zaman alacağı için paket sayınızı düşürmenizde fayda var. Ben genelde 250 – 500 arasında bir değer seçiyorum, bu sayede hem Dynamics 365 tarafında oluşacak yükü azaltmış oluyorum hem de işlem yapmak istediğim data boyutunu kabul edilebilir bir zamanda bitiriyorum.

Elbette bu sayıyı çalıştığınız sistemin ve projenin gereksinimlerine göre bir kaç test yaparak çok rahatlıkla belirleyebilirsiniz.

3. Hata Senaryolarının Tespit Edilmesi ve Gerekli Akışların Oluşturulması

Belki de projelerde yaptığımız en sık hatalardan birisi ExecuteMultipleRequest ‘in hata senaryolarının düşünmemek ve bunlar için bir geliştirme yapmamak.

Daha önce belirttiğim gibi ExecuteMultipleRequest içinde yer alan her bir request kendi transaction yapısına sahiptir ve diğer işlemleri etkilemez, bu nedenle tüm işlemler için geçerli bir rollback mekanizması yoktur. Eğer kritik süreçlerinizde ExecuteMultipleRequest yapısını kullanıyorsanız hata ihtimallerini göz önüne alarak buna uygun akışlar oluşturmanızı öneririm.

Muhtemelen ExecuteMultipleRequest için oluşturulmuş en kapsamlı yazı oldu 🙂 umarım faydalı olmuştur.

Dynamics 365 CE (CRM) SDK mesajları hakkında tüm yazılara tek nokta üzerinden ulaşmak isterseniz https://www.emregulcan.com/microsoft-xrm-sdk-messages adresine bakabilirsiniz.

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 cevap yazın

E-posta hesabınız yayımlanmayacak.

This site uses Akismet to reduce spam. Learn how your comment data is processed.