Updating Records in a Plugin without blowing up your Audit Log

If you’ve ever worked on a Dynamics 365 (CRM) plugin where you were updating data on an existing record, you may have run across a strange phenomenon.  The Plugin engine will send you a copy of the postImageEntity, which is an object of type Entity and is a copy of the current record you are working with.

Example:

IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
 
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
 
Entity postImageEntity = (context.PostEntityImages != null && context.PostEntityImages.Contains("Target")) ? context.PostEntityImages["Target"] : null;

 

From this new variable, you can set the value of one of the fields and write the record back to Dynamics.  Let’s say we want to update the Account Number field on the Account Entity to the first 3 characters of the Account Name.

postImageEntity["accountnumber"] = postImageEntity["name"].ToString().Substring(0, 3);
 
service.Update(postImageEntity);

So all looks correct, right?  Well, sort of.

While technically this code works, there is a catch.  If you run this code and have auditing turned on for your Account entity you will see something odd.  You will see that the ENTIRE record is loaded into the Audit record with all the before and after field values being exactly the same with the exception of the Account Number.

If you have unlimited storage space available and keep your audit records forever, then you don’t have a problem.  If you are like the other 99% of us that need to be frugal with storage space, especially with Dynamics online, then you need a better solution.  Besides, who can read an audit where every single field is written back and you try to find the 1 field that was actually updated.

If you look at the code, it actually makes sense why it did it that way… postImageEntity contains every field on the record.  All we did was to update one field and write the whole thing back.  It doesn’t care that you only updated one field…like a good C# function it’s doing what you told it to do.

So here’s a solution.  You need to declare another variable of type Entity, update that one with the new value, and write that back to the system.

I have a helper function that does this that I use in all my plugin projects.

public static Entity getEntityForUpdate(IOrganizationService service, string EntityName, Guid EntityRecordId)
{
/*
====================================================================
Chris H:
Here we are declaring a separate entity object to use strictly 
for updating values on the Record
If we just update the postImageEntity, it updates 
EVERY field on the record, not just the ones that are 
being updated which makes the audit logging look bizarre.
=====================================================================
*/
Entity _Entity = new Entity(EntityName);
ColumnSet _EntityAttributes = new ColumnSet(new string[] { EntityName + "id" });
_Entity = service.Retrieve(_Entity.LogicalName, EntityRecordId, _EntityAttributes);
return _Entity;
}

Now what you do at the beginning of you plugin code is declare this Entity variable, update it, and write it back.

Entity record2Update = getEntityForUpdate(service, postImageEntity.LogicalName, postImageEntity.Id);
 
record2Update["accountnumber"] = postImageEntity["name"].ToString().Substring(0, 3);
 
service.Update(record2Update);

Hopefully this makes sense, if not just send me a comment I can clarify.

Disclaimer:  I am NOT a classically trained developer.  I have basically learned how to write .NET code by copying the work of others and modifying it for my own needs.  I’ve learned a few tips over the years and hope that you find them useful.  Enjoy!

Leave a Reply

Your email address will not be published. Required fields are marked *

Do some math and prove your not a robot... *