January 20, 2015

Get the Id of records created using Early Bound OrganizationServiceContext

The other day my friend Raj (@RajYRaman) retweeted a post from Dynamics CRM PFE Team about the best practice to let CRM to choose the Guid of new records instead of using Guid.NewGuid():

http://blogs.msdn.com/b/crminthefield/archive/2015/01/19/the-dangers-of-guid-newguid.aspx

With IOrganizationService object is very easy to get the Id of the new record, because it's the value returned by the Create method independently if late bound or early bound is used:
IOrganizationService service = new OrganizationService(crmConnection);

// late bound
Entity lateAccount = new Entity("account");
lateAccount["name"] = "Late Bound Account";
Guid lateAccountId = service.Create(lateAccount);

// early bound
Account earlyAccount = new Account();
earlyAccount.Name = "Early Bound Account";
Guid earlyAccountId = service.Create(earlyAccount);
This works because Early Bound classes inherit from the Entity class.
public partial class Account : Microsoft.Xrm.Sdk.Entity ...
But how we can get the Id of the records when we use the OrganizationServiceContext in combination with the AddObject and SaveChanges methods?
Using Guid.NewGuid() in order to specify the Id before creating the record was one of my mistakes when I first used Early Bound classes. My badly written code was:
IOrganizationService service = new OrganizationService(crmConnection);
XrmContext context = new XrmContext(service);

// WORST CODE EVER, DON'T DO THIS!
Account earlyAccount = new Account();
Guid badGeneratedId = Guid.NewGuid();
earlyAccount.Id = badGeneratedId;
earlyAccount.Name = "Early Bound Account";
context.AddObject(earlyAccount);
context.SaveChanges();
The reason was to avoid parsing the results of the SaveChanges method in order to get the Id. SaveChanges doesn't return void but a SaveChangesResultCollection object with the details of the save operation.

But checking the results is not necessary, in fact the OrganizationServiceContext updates the tracked records adding the Guid value to the Id property. We just need to read the Id property after the SaveChanges:
Account earlyAccount = new Account();
earlyAccount.Name = "Early Bound Account";
context.AddObject(earlyAccount);
context.SaveChanges();

Guid crmGeneratedId = earlyAccount.Id; 
MSDN Documentation (at least at the time I discover this) isn't so clear explaining this behavior, hope it helps!

1 comment:

  1. Yes another great explanation and saving me trouble with the SDK taking me down that NewGuid() path. yuck. This was very helpful setting up the xRM portal.

    ReplyDelete