C# Code · Dynamics Plugins

{Dynamics CRM 365} Implement Locking mechanism using C#

While working on one of the requirement where we needed to generate unique ID for the Custom Entity record. We thought of using plugin code to implement Auto number generate unique ID. However when multiple records were getting created from integrations and various sources, many duplicated IDs were getting generated.

After invetsigating further and multiple search on internet, we finally decided to use lock mechanism which is provided by .net framewrok.

C# Code to Generate ID using lock 

Class Helper
{
private static object lockObj = new object();

public static string GenerateId()
{
lock (Helper.lockObj)
{
Thread.Sleep(100);
string empty = string.Empty;
DateTime now = DateTime.Now;
string str1 = now.Year.ToString((IFormatProvider)CultureInfo.InvariantCulture);
now = DateTime.Now;
int month = now.Month;
string str2 = month < 10 ? "0" + month.ToString() : month.ToString();
now = DateTime.Now;
int day = now.Day;
string str3 = day < 10 ? "0" + day.ToString() : day.ToString();
now = DateTime.Now;
int hour = now.Hour;
string str4 = hour < 10 ? "0" + hour.ToString() : hour.ToString();
now = DateTime.Now;
int minute = now.Minute;
string str5 = minute < 10 ? "0" + minute.ToString() : minute.ToString();
now = DateTime.Now;
int second = now.Second;
string str6 = second < 10 ? "0" + second.ToString() : second.ToString();
now = DateTime.Now;
int millisecond = now.Millisecond;
string str7 = millisecond < 10 ? "0" + millisecond.ToString().Substring(0, 1) : millisecond.ToString().Substring(0, 1);
int num = new Random().Next(100, 999);
return empty + str1 + str2 + str3 + str4 + str5 + str6 + str7 + num.ToString();
}
}
}

Lock

C# Lock keyword ensures that one thread is executing a piece of code at one time. The lock keyword ensures that one thread does not enter a critical section of code while another thread is in that critical section.

Lock is a keyword shortcut for acquiring a lock for the piece of code for only one thread.

Hope this helps!

6 thoughts on “{Dynamics CRM 365} Implement Locking mechanism using C#

  1. Hi Bipin,

    I am faced by a similar issues, but from what I can tell this implementation would not work as plugins run in their own sandbox, likely on different servers as well. Any idea how this could be solved?

    Like

  2. Hi, this is simply not enough… this might work in an onprem crm where your plugin is beeing executed by one sandbox service on one machine where the appdomain of the plugin execution is simply reused by all executions. This will definitely not work in load-balanced crm backend server clusters, you dont have the certainty that your sandbox plugin execution is happening within same app domain, neither on same machine. This is simply not enough. You need some not even inter-process but iter-machine locking mechanism, thus most probably calling some hand crafted external service to hold the locks and block uppon this locking remote call.

    Like

  3. Oh my god, first-hand example of how to NOT do locking in D365 plugins. The C# “lock” keyword is used for locking resources betwen threads running within the same process. – The issue is that in D365 Online this is definitely not the case, and On-Prem you cannot guarantee it (and you do NOT want to limit to 1 worker process).

    Instead, you use the built-in optimistic lock mechanism with some error handling logic in case of version mismatches. – This could be implemented using Polly for .NET.

    In this specific case though, a row-lock is more appropriate:
    1) As the very first thing in the plugin do a bogus update on the row containing the autonumber counter. – This creates a Row Lock on database-level, so in essence a lock across all worker processes.
    2) Read the autonumber counter from that row again (now that we have a lock).
    3) Use the number to insert on whatever target entity.
    4) Update the row with the next autonumber.
    5) Plugin finishes and releases the row lock so that the next plugin in line may read from it.

    Make sure to use “context.MergeOption = Microsoft.Xrm.Sdk.Client.MergeOption.NoTracking” in order to ensure that any values are not read from some cache (just in case).

    There are possibilities of deadlocks using this method, so in case that happens, Polly for .NET as a resilience framework for defining retry policies is worth gold 🙂

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s