Customer Engagement & Dynamics CRM Forum

Expand all | Collapse all

Update Only Specified Fields after a CRM Fetch

  • 1.  Update Only Specified Fields after a CRM Fetch

    Posted Feb 18, 2020 01:34 PM
    Edited by Tim Neau Feb 18, 2020 01:54 PM
    ​I'm working on a CRM plugin in C# that updates the status of one entity based on the target entity that the plugin is trigger by, while also updating the target entity with information from the entity that I'm updating the status on.

    What I'm seeing is that the entity I update the status on is also having the fields in the fetch being updated, even though no change has been made to them. The update then causes a workflow to kick off and cause an unnecessary re-name of the entity.

    Is there a way to "ignore" the fields that I'm reading while only updating the status field on the fetched entity? I tried creating a new Entity object with the same ID and only setting the status field, but it didn't actually update the entity (no error though).

    Update:
    Looks like I can use the .Copy() on the fetched and .Attributes.Clear() before updating the status and it works as expected.

    #CustomerEngagement
    ​​#Functional
    #CRM2016​​

    ------------------------------
    Tim Neau
    Systems Developer
    Federated Insurance
    Owatonna MN
    ------------------------------
    The first step toward cloud success. - Migrate from CRM to D365 with expert guidance from Microsoft. I'm Ready


  • 2.  RE: Update Only Specified Fields after a CRM Fetch

    MICROSOFT MVP
    Posted Feb 19, 2020 04:01 AM
    Hi Tim

    This is one of the classic mistakes in plugins - you're not alone :)
    What you need to do is instantiate a new Entity for the record you want to update, with only the attributes to update added to it.
    If you have a record instantiated as myContact with "too many" attributes, you can do something like this (written freely here, in case something is not 100% accurate)
    var updContact = new Entity(myContact.Name, myContact.Id);
    updContact.Attributes.Add("myattributename", myValue);
    // repeat ^^ for attributes to be updated
    myService.Update(updContact);


    ------------------------------
    Jonas Rapp
    MVP
    Sweden
    ------------------------------

    The first step toward cloud success. - Migrate from CRM to D365 with expert guidance from Microsoft. I'm Ready


  • 3.  RE: Update Only Specified Fields after a CRM Fetch

    Posted Feb 19, 2020 08:34 AM
    Hi Jonas,

    That was my original approach and it wasn't actually updating the entity. Though I did the attribute add syntax a little differently:

    var updContact = new Entity(myContact.Name, myContact.Id);
    updContact["myattributename"] = myValue;
    // repeat ^^ for attributes to be updated
    myService.Update(updContact);


    I will give it another try using the .Add() instead.



    ------------------------------
    Tim Neau
    Systems Developer
    Federated Insurance
    Owatonna MN
    ------------------------------

    The first step toward cloud success. - Migrate from CRM to D365 with expert guidance from Microsoft. I'm Ready


  • 4.  RE: Update Only Specified Fields after a CRM Fetch

    MICROSOFT MVP
    Posted Feb 19, 2020 09:23 AM
    Your approach is completely valid and will result in the same exact thing as Jonas.  My guess is that the plugin didn't get published correctly.

    I tend to stay away from Change tracking as mentioned by @Rex Kenley Tan only because it complicates things (like knowing if an entity is attached to the context for change tracking or not)​

    ------------------------------
    Daryl LaBar
    President, MVP
    Gap Integrity
    Fishers IN
    ------------------------------

    The first step toward cloud success. - Migrate from CRM to D365 with expert guidance from Microsoft. I'm Ready


  • 5.  RE: Update Only Specified Fields after a CRM Fetch

    Posted Feb 19, 2020 09:29 AM
    Thanks Daryl. Turns out I was still passing the original object instead of my new Entity into the Update() method. It works as expected now.

    ------------------------------
    Tim Neau
    Systems Developer
    Federated Insurance
    Owatonna MN
    ------------------------------

    The first step toward cloud success. - Migrate from CRM to D365 with expert guidance from Microsoft. I'm Ready


  • 6.  RE: Update Only Specified Fields after a CRM Fetch

    TOP CONTRIBUTOR
    Posted Feb 19, 2020 09:50 AM
    @Daryl LaBar

    In what plugin use cases would knowing which context is necessary? Plugins run in a transaction so there should be only only one default context, correct?

    Thanks!​

    ------------------------------
    Rex Kenley Tan, MCSA, MCSD
    Tallmadge OH
    https://www.youracclaim.com/users/rex-kenley-tan

    *Always be CURRENT with JavaScript & C#, NEVER be obsolete.

    DISCLAIMER: All views expressed on this site are my own and DO NOT represent the opinions of ANY entity whatsoever with which I have been, am now, or will be affiliated.
    ------------------------------

    The first step toward cloud success. - Migrate from CRM to D365 with expert guidance from Microsoft. I'm Ready


  • 7.  RE: Update Only Specified Fields after a CRM Fetch

    MICROSOFT MVP
    Posted Feb 19, 2020 09:56 AM
    I'm talking about the Organization Context.  Maybe the version in that you use in the XrmToolKit works different than the one MS released back in 2011?  If you created a new instance, you had to add that instance to the context, so it could start doing the change tracking.  Just seemed to be the source bugs from devs using it incorrectly so much, that it wasn't worth any readability improvements that it offered.  But this is all IMHO.  I won't ever say that it's bad, or that it's wrong, or anything like that.  My personal opinion is it causes more issues than it's worth.

    ------------------------------
    Daryl LaBar
    President, MVP
    Gap Integrity
    Fishers IN
    ------------------------------

    The first step toward cloud success. - Migrate from CRM to D365 with expert guidance from Microsoft. I'm Ready


  • 8.  RE: Update Only Specified Fields after a CRM Fetch

    TOP CONTRIBUTOR
    Posted Feb 19, 2020 10:04 AM
    Thanks for the clarification. I was concerned that this maybe something potentially problematic.

    From what I could find, it always binds itself to the local context.
    Templates for plugins and custom workflows that use a 'LocalContext' to provide easy access to the following: ITracingService, IOrganizationContext, Pre and Post images, and the target entity or entity reference.

    https://xrmtoolkit.com/Home/Features


    ------------------------------
    Rex Kenley Tan, MCSA, MCSD
    Tallmadge OH
    https://www.youracclaim.com/users/rex-kenley-tan

    *Always be CURRENT with JavaScript & C#, NEVER be obsolete.

    DISCLAIMER: All views expressed on this site are my own and DO NOT represent the opinions of ANY entity whatsoever with which I have been, am now, or will be affiliated.
    ------------------------------

    The first step toward cloud success. - Migrate from CRM to D365 with expert guidance from Microsoft. I'm Ready


  • 9.  RE: Update Only Specified Fields after a CRM Fetch

    TOP CONTRIBUTOR
    Posted Feb 19, 2020 07:11 AM
    @Tim Neau

    I would highly recommend the xrmToolkit (not toolbox). It automatically generates proxy entities that takes care of a lot of these "gotchas". So you don't to worry about it and just focus on what you need to do with your plugins. *Although it is still good practice to only retrieve the fields that you need.

    https://xrmtoolkit.com/

    Early bound classes.
    Change tracking - When updating an entity, only push the properties that have changed to CRM instead of all properties that have a value. This helps reduce the noise and size of the audit logs as only the properties that have changed are logged to CRM. This also improves the speed of custom applications that process large amounts of data since only records that are changed push to CRM. If a records values do not change then 'Saving' the record does not create an 'Update' request.

    ------------------------------
    Rex Kenley Tan, MCSA, MCSD
    Tallmadge OH
    https://www.youracclaim.com/users/rex-kenley-tan

    *Always be CURRENT with JavaScript & C#, NEVER be obsolete.

    DISCLAIMER: All views expressed on this site are my own and DO NOT represent the opinions of ANY entity whatsoever with which I have been, am now, or will be affiliated.
    ------------------------------

    The first step toward cloud success. - Migrate from CRM to D365 with expert guidance from Microsoft. I'm Ready


  • 10.  RE: Update Only Specified Fields after a CRM Fetch

    TOP CONTRIBUTOR
    Posted Feb 20, 2020 10:12 AM
    Edited by Gerry Yurko Feb 20, 2020 12:44 PM
    Let me throw in my thoughts on this subject.

    What I find in Plugins is that whatever field is included in the "update Entity" ( I usually just call it updateEntity) will update even if the Value hasn't changed.  This will show up in the Audit History as the Field changing to its already existing Value and possibly triggering Workflows unnecessarily.

    You therefore have to compare your Value with the Entity to update on a Field by Field basis to see if it has changed.  .The scenario is usually a change has been made in one Entity and needs to update a different Entity.

    My solution is to run a nested if of each field to see if the Value has changed.  Like this:

    I am totaling Values iterating through child Records of the Order.  If the totaled Value changes then include the Attribute in the updateEntity

    if (TestIfChanged(getOrder, "new_cancelednrc", cannrc))
    updateEntity["new_cancelednrc"] = new Money(cannrc);
    if (TestIfChanged(getOrder, "new_canceledmrc", canmrc))
    updateEntity["new_canceledmrc"] = new Money(canmrc);
    if (TestIfChanged(getOrder, "new_canceledincrementalmrc", canIncremt))
    updateEntity["new_canceledincrementalmrc"] = new Money(canIncremt);
    if (TestIfChanged(getOrder, "new_canceledoffnetcost", canoffnet))
    updateEntity["new_canceledoffnetcost"] = new Money(canoffnet);

    The TestifChanged method returns true or false based on if the value changed or not:

    public static bool testIfChanged(EntityCollection Entity, string getField, Decimal calcValue)
    {
    if (Entity[0].Contains(getField)) {
    Decimal getFieldValue = ((Money)Entity[0][getField]).Value;
    if (getFieldValue != calcValue)
    return true;
    } else if (calcValue != 0) {
    return true;
    }
    return false;
    }

    I would love for there to be an easier way but I have yet to discover it.

    It's pretty obvious by the Code, but I'm using early-bound.

    ------------------------------
    Gerry Yurko
    CRM Developer
    Crown Castle Fiber Networks
    Boxborough MA
    ------------------------------

    The first step toward cloud success. - Migrate from CRM to D365 with expert guidance from Microsoft. I'm Ready


If you've found this thread useful, dive deeper into User Group community content by role