Last week, we publically released a C# .NET library for Dynamics CRM that's the result of multiple customer and partner advisory engagements. Predictably, for every development question we answer or recommendation we provide, a request for a code sample to illustrate the concept is sure to follow. When authoring code samples for customers and partners, we found ourselves continually writing similar code to connect to and maximize request throughput with Dynamics CRM services regardless of the scenario. We began to consolidate our techniques into a library that we then delivered as a foundational component to our sample solutions. Over time, the patterns in the library evolved and have been further refined. Fast forward to today, we felt that openly sharing the result of our journey, education and mentoring others, will at best offer insight into new techniques or at a minimum validate what you already know and practice.
What is it?
The PFE Dynamics Core library for Dynamics CRM is a managed C# .NET library that can be included in .NET projects needing to directly communicate with Dynamics CRM services. What does the library offer? Primarily two objectives, 1) efficiently authenticate and establish communication channels, and 2) provide an easy interface to parallelize requests for maximum throughput. The former simply builds on techniques and constructs offered in the CRM SDK. Whereas the latter is a play on the IDiscoveryService and IOrganizationService service operations, where equivalent methods, each accepting a collection of requests, abstract the actual implementation of parallelized processing. To the developer, an operation involving many CRM service requests can be quickly parallelized in a single line of code. Interested in the meat? Check out these two code files: XrmServiceManager.cs and ParallelServiceProxy.cs. You'll also find a few other goodies sprinkled in.
Where can I get it?
If you just want to reference the assembly, we have versions for Dynamics CRM 2013 (v6) and 2011 (v5) available on NuGet.org. Simply install the appropriate package into your project to get the latest version and be kept up to date on future releases. We even built in a dependency on the appropriate CRM SDK Core Assemblies package for each version, so adding our package is a one-stop shop for getting connected to CRM. Otherwise, if it is source code that you're after, head on over to our CodePlex project site. In addition to source code, you'll find documentation, release notes, and ability to contribute feedback.
First, we have a few minor refinements queued for a 1406.0 build that further optimize our patterns. We also plan to expand the documentation and supplement with some examples of how to use the library. From there we anticipate additional improvements that are driven by upcoming CRM product releases (Leo and beyond). Lastly, we're always looking for notable and repeatable techniques that can benefit the broader community from our day-to-day advisory work, including feedback we receive via the project site, our blog, twitter, etc.
By publishing this library, we hope to drive awareness for best-practices when communicating with Dynamics CRM services, increase the performance of your .NET applications, and possibly eliminate some redundant code in the process. We would love to hear your story about tackling similar challenge, ideas for improvement, or even how our library has directly or indirectly benefited your solution. Comment below, suggest a feature on our CodePlex project site, or contact our team directly!
M. Austin Jones
Follow the conversation:@maustinjones@pfedynamics | http://www.pfedynamics.com
Do your queued refinements include making use of the ExecuteMultiple message? I was surprised to see no mention of it in the post or the code, considering its applicability to increasing throughput.
Interesting that you mention ExecuteMultiple. First, an ExecuteMultipleRequest will only increase throughput over high-latency connections between service client and endpoint, because you only pay the latency penalty twice for a batch of requests rather than twice for each individual request. Otherwise, the requests contained in an ExecuteMultipleRequest are processed sequentially on the server as if you were submitting them sequentially from the service client. That said, you can achieve the best of both worlds by balancing your batch size with parallelized ExecuteMultipleRequests.
Second, because ExecuteMultipleRequest is just another variation of OrganizationRequest, it is valid to be submitted via our library's .Execute(IList<OrganizationRequest>) or .Execute<TRequest, TResponse>(IList<TRequest>) methods. The only caveat is that for CRM Online environments, you would need to throttle max degrees of parallelization on our ParallelOrganizationServiceProxy class so as not to exceed the ExecuteMultipleRequest concurrency limits in place on the CRM server.
Personally, I see no benefit in ExecuteMultipleRequest for on-premise deployments where you have minimal latency between service client and endpoint. In fact, you become more bound to sequential processing as well as potential channel timeout limits which means your operation may realize decreased performance and reliability.
Does your .Execute<TRequest, TResponse>(IList<TRequest>) method keep going even if there are some failures with some of the requests..
@SM - As of the 1503 build, we will handle the FaultException<T> if you specify an error handling delegate. Essentially, we collect them up in the parallel iterations and then pass them in sequential delegate function calls after all parallel processing is complete. If you don't specify the handler, we revert to default TPL handling of exceptions where all are caught and current iterations are notified of loop termination. then an AggregateException is returned. This means that all exceptions from currently executing iterations will be returned, but that no remaining iterations will be started. I updated the documentation/samples to more clearly explain this and provide a pointer to the MSDN article on TPL exception handling: pfexrmcore.codeplex.com/wikipage
Hope that helps!!