At the core of Microsoft’s tooling library (Microsoft.CrmSdk.XrmTooling.CoreAssembly), there resides the out-of-the-box CrmServiceClient class. It provides developers with the means to connect to CRM easily and the convenience of some helpers methods. On its own, the class is a perfect fit for small-scale applications, with a single purpose, and low throughput.

This leaves enterprise-grade applications in a bit of a pickle. Herein lies the opportunity to introduce a solution that preserves the integrity of the original design, but adds some critical enhancements for large-scale, heavy-hitting applications: EnhancedOrgService.

TL;DR

  • Microsoft’s libraries
    • OrganizationServiceProxy has thread-safety issues
    • Causes serious random problems on high load systems
    • Replaced by the more robust CrmServiceClient some time ago
    • CrmServiceClientis slower in high throughput applications
  • EnhancedOrgService library
    • Greatly improves the performance of your application, and resolves safety issues
    • Virtually indistinguishable and interchangeable with IOrganizationService
    • Includes many other cool features:
      • Auto-retry, response caching, operation events and statistics
      • Robust load balancer
      • In-memory transactions, deferred execution, and fast planned execution on CRM server
  • Install: here
  • Quick connect: var service = EnhancedServiceHelper.GetPoolingService("<connection-string>", <connection-count>);

Original Issue

Microsoft noticed an issue with the older version: OrganizationServiceProxy, in that, it was problematic when it came to thread safety. Most notably, it caused random errors when multiple threads made calls to CRM in parallel. The issues were notoriously hard to trace as well.

In the new library incarnation, Microsoft introduced a lock around each internal channel access. This guaranteed that novice developers are unburdened by thread-safety concerns, which is in fact an advanced topic for most and requires some decent experience.

Locking to wait for an HTTP response is a major performance drawback, in this case. This is very evident when the CrmServiceClient class is used in web services or high throughput applications; e.g. data migration.

Pooling Pattern

A slightly more experienced team would simply resolve the aforementioned issues by implementing a pooling pattern. In other words, their solution would maintain multiple connections in a pool, developers would request a connection from the pool to use and then release the connection to the pool when done.

This has to be done by each team individually in our community, and the solution must be thoroughly tested as it lies at the core of all logic, which could be catastrophic if an issue arises on Live.

EnhancedOrgService

EnhancedOrgService is a custom library that acts as a common component for all CrmServiceClient enhancements. It provides the following features:

  • Automatic service pool handling (core feature)
  • Connection warmup to improve initialisation performance (optional)
  • Caching of operation results (optional)
  • Automatic retry of failed operations (optional)
  • Operation events and statistics
  • Load balancer algorithms for multi-node environments
  • In-memory transactions
  • Deferred operations to run in a transaction
    • Accumulate operations from across the application to be executed in one go
  • Planned execution to be sent to CRM for execution
    • Return values from mid-execution operations can be used in later operations within the same transaction

I will go over the core features in this article, and then expand on the optional ones in later articles.

Let’s Automate

The library takes the pooling pattern a step further and tries to alleviate the whole thing off the developer’s shoulders. At the heart of the library lies automation logic for handling the aforementioned pooling control altogether. All the developer has to do is specify the number of services, and an internal pool is automatically created and managed by the library for maximum performance.

Installation

To install the library into a project, search for Yagasoft on NuGet, or access the page here.

Connecting to CRM

Core Internal Components

There are a couple of components required for connection:

  1. EnhancedServiceParams: contains parameters that can be used to fine-tune a lot of aspects of the service and its operations
  2. IEnhancedServiceFactory: the source of the vanilla CRM connections and where the IEnhancedOrgService object is created
  3. IEnhancedServicePool: implementation of the Object Pool pattern previously mentioned
  4. IEnhancedOrgService: where all the internal pooling occurs and most of the features can be invoked

There are two basic approaches to creating a connection to CRM in EnhancedOrgService.

Implicit Factory Using Helpers

  1. Create the pool
  2. Request a simple connection/service
1
2
var pool = EnhancedServiceHelper.GetPool("<connection-string>", 5);
var service = pool.GetService();

Explicit Factory

  1. Define the parameters
  2. Create a factory
  3. Create the pool
  4. Request a service
1
2
3
4
var parameters = new EnhancedServiceParams("<connection-string>");
var factory = new EnhancedServiceFactory<IEnhancedOrgService, EnhancedOrgService>(parameters);
var pool = new EnhancedServicePool<IEnhancedOrgService, EnhancedOrgService>(factory, 5);
var service = pool.GetService();

This method is useful when finer control is required; e.g. cache-control over the factory (explained in a later article). In addition, in the future, new service types might be introduced for extra choice by the developer.

Pool Management

Here, there are three basic methods of controlling the pool.

Implicit

This is a new addition to the library, and in my opinion, it’s the best way to go.

The pooling mechanics are fully managed. Using the service is identical to the out-of-the-box one.

Using helpers:

1
var service = EnhancedServiceHelper.GetPoolingService("<connection-string>", 5);

Or manually:

1
2
3
4
var connectionString = "<connection-string>";
var pool = new DefaultServicePool(connectionString, 5);
var factory = new DefaultEnhancedFactory(connectionString);
var service = factory.CreateService(pool);

Here, a CrmServiceClient pool is created with a 5-connection limit, a quick factory is created, and then the service is requested with an internally managed pool defined earlier. There is no need to dispose of the service at all throughout its lifetime in this case.

The way it works is that whenever an internal operation needs to call CRM, a connection is automatically requested from the pool, and then released back to the pool at the most optimal moment in the logic. This logic is completely transparent to the developer, and it guarantees that no starvation will occur.

Please note that the internal pool’s connections are lazily created unless a ‘warm up’ is initiated on the pool or service.

Explicit

Simply, request a service from the pool, use it, and then dispose to return it to the pool.

This method might not fit the development style of some teams; check the ‘implicit’ method below, instead.

1
2
3
4
using (var service = pool.GetService())
{
     // code
}

The biggest challenge is that the developer needs to decide on the best moment to dispose of the service: keep it in hand too long, and you starve other logic; forget to dispose of the service, and you end up exhausting the pool with an eventual dead-lock.

Please note that connections in the pool are lazily created upon request unless a warm-up is explicitly initiated.

Conclusion

This part was a quick introduction to the library. We went over the reason for its existence and the most important feature.


In the next part of the article, I will introduce more advanced features: performance enhancements, auto-retry, stats, events, and caching.

Leave A Comment