How to – Immediately (sync)bulk delete AsyncOperation or Workflow System Job records in Dataverse (Dynamics 365 / CRM)


Recently we noticed File usage of some of our environments reaching around 50 GB, and most of it was because of the AsyncOperation table.

async

So to quickly delete the AscyncOperation records the option we can choose is –

Create a new Bulk Record Deletion job from Settings >> Data Management

Select System Jobs table and filter as System Job Type equals Workflow

Select Bulk deletion job start time as Immediately

The Immediately option will only be available –

  • For entity – System Jobs
  • Filter Criteria is System Job type equals Workflow (we can add additional criteria)
  • User has organization-level
    delete rights on AsyncOpertion entity.

This will only delete the AsyncOperation records that are in the completed state of system job type workflow.

It will delete 1 million records whenever it is run. If there are more than 1 million records, it will have to be run again.

The key part is that it will delete the records through direct SQL Execution, so the records will be deleted immediately, rather than each record going through the delete pipeline, thus improving the performance immensely.

Back to our bulk deletion job, we can click on Submit to initiate the deletion.

We encountered a few errors when submitting, the solution was to keep trying, and eventually it will get submitted successfully.

error

After successful submission, we can see all our completed workflow system job records deleted immediately.

Also as it is Sync Job, we will not see it listed in Bulk Record Deletion views.

Get more details here –

https://cloudblogs.microsoft.com/dynamics365/it/2018/06/21/cleaning-up-records-from-the-asyncoperationbase-workflowlogbase-table/

https://docs.microsoft.com/en-us/power-platform/admin/free-storage-space#reduce-file-storage

Hope it helps..

Advertisements

Microsoft.Crm.CrmException: An application user’s access mode cannot be changed error in Dataverse (Dynamics 365 / CRM)


Just a short one –

As the error message suggests “An application user’s access mode cannot be changed “, it is not possible to change the Access mode of an application user from Non-interactive to either administrative or Read-write.

While trying to change the Application User’s Access Mode to Read-Write, the error message –

Get all the details about different type of users –

https://docs.microsoft.com/en-us/power-platform/admin/create-users#user-types

also check – https://community.dynamics.com/365/sales/f/dynamics-365-for-sales-forum/367844/when-uisng-non-interactive-users-when-using-application-users

Hope it helps..

Advertisements

Sample Code – Update format of Autonumber attribute in Dataverse (Dynamics 365 / CRM)


At times we may have a requirement to update the format of the Auto Number dynamically / programmatically so that the new set of records take up the new format.

Let us understand through a simple example.

Right now for the below field, we have the auto-number format set as

{SEQNUM:4}


Below is the sample code to update the auto-number format programmatically.

It makes use of our RetrieveAttribute and UpdateAttribute requests.

https://docs.microsoft.com/en-us/dynamics365/customerengagement/on-premises/developer/create-auto-number-attributes?view=op-9-1#autonumberformat-options

We have retrieved the attribute then have specified a new auto number format, followed by update request.

After executing the above code successfully, and creating a new contact record we can see the new number generated as per the specified format.

Sample Code

        string ConnectionString = "AuthType = OAuth; " +
              "AppId=51f81489-12ee-4a9e-aaae-a2591f45987d; " +
              "Username=test@test.onmicrosoft.com; " +
              "Password=test; " +
              "RedirectUri=app://58145B91-0C36-4500-8554-080854F2AC97;" +
              "Url = https://test.crm.dynamics.com/;";


        CrmServiceClient svc = new CrmServiceClient(ConnectionString);

        if (svc.IsReady)
        {
            var retAttributeRequest = ((RetrieveAttributeResponse)
                             svc.Execute(new RetrieveAttributeRequest
                             {
                                 EntityLogicalName = "contact",
                                 LogicalName = "cr59f_myautonumber",
                                 RetrieveAsIfPublished = true
                             })).AttributeMetadata;

            retAttributeRequest.AutoNumberFormat = "MyFormat-{SEQNUM:6}-{DATETIMEUTC:yyyyMMddhh}-{RANDSTRING:6}";

            var updateAttrRequest = new UpdateAttributeRequest
            {
                EntityName = "contact",
                Attribute = retAttributeRequest
            };

            var updateAttrResponse = (UpdateAttributeResponse)
                svc.Execute(updateAttrRequest);

Check other posts on Auto Number attribute –

Hope it helps..

Advertisements

Manage and share views in Modern Advanced Find – Dataverse (Dynamics 365 / CRM)


Let us have a quick look at this new feature introduced as part of 2022 Release Wave 1.

Make sure we have updated the environment to 2022 Release Wave 1.

Then navigate to [Environment] >> Settings >> Features

Switch On – Modern Advanced Find and Allow users to hide system view 


Reset Default View
is the only option available before we switch on the Modern Advanced find feature.


After enabling the Modern Advanced Find feature

We get the option to Search Views as well as Manage and share views


Search Views – It allows us to filter / search within the views.


Manage and share views – It opens the dialog listing the views.


We can sort by

  • Personal before system, A to Z
  • System before personal, A to Z
  • A to Z


To hide a view we can select hover and select the option to hide.

With Allow users to hide system views  option switched on, the user has the option to hide system view also, else he could only hide the personal views.


For System Views, we have the option to either Hide or Set as a default view.

For Personal Views, we have more options like 

Hide, Set as default view, Share etc. as shown below.

Learn everything about the new Modern Advanced Find View  – https://jukkaniiranen.com/2022/02/modern-advanced-find-test-drive/

https://powerapps.microsoft.com/en-us/blog/modern-advanced-find-with-enhanced-view-management-in-model-driven-apps/

Hope it helps..

Advertisements

How to – Use SetAutoNumberSeed Action to reset/update the seed for the Autonumber attribute – DataVerse (Dynamics 365 / CRM)


Suppose we have the following Autonumber field created with

Seed value1000 and Format{SEQNUM:4}

Now based on a certain requirement, we want to dynamically / programmatically update / reset the seed value.

For this, we can make use SetAutoNumberSeed Action

Below we can see the auto number set as 1007 on creating a new contact record.

Now to set it back to 1000 we can run the following code –

On executing the action, we can see the next contact record having autonumber field set as 1000.

Another example –

On updating the value to 888, and creating a new contact record

Sample code –

                OrganizationRequest customActionRequest =
                    new OrganizationRequest("SetAutoNumberSeed");

                // name of the entity
                customActionRequest["EntityName"] = "contact";

                // attribute's schema name
                customActionRequest["AttributeName"] = "cr59f_myautonumber";

                // the value we want to set
                customActionRequest["Value"] = Convert.ToInt64(888);

                OrganizationResponse customActionResponse = 
                    svc.Execute(customActionRequest);

Check other posts –

https://powerobjects.com/tips-and-tricks/auto-number-d365-version-9/

Hope it helps..

Advertisements

How to – Use RetrieveAttributeChangeHistoryRequest to get audit data for an attribute (Dataverse/ Dynamics 365/ CRM)


We can use RetrieveAttributeChangeHistoryRequest to get the change history of a particular field / attribute of a record.

We need to set the Target and the AttributeLogicalName property of the request.

AuditDetails records of the RetrieveAttributeChangeHistoryResponse contains the detail of the audit records.

The Audit History records in CRM- 

AttributeAuditDetail contains the details of the changes made on the field’s value. It contains property like – objectid, userid, operation etc. as well as new value and the old value as shown below.

Sample Code (C#) 

 string ConnectionString = "AuthType = OAuth; " +
                  "AppId=51f81489-12ee-4a9e-aaae-a2591f45987d; " +
                  "Username=User1@xxxx.onmicrosoft.com; " +
                  "Password=*******; " +
                  "RedirectUri=app://58145B91-0C36-4500-8554-080854F2AC97;" +
                  "Url = https://xxx.crm.dynamics.com//;";


            CrmServiceClient svc = new CrmServiceClient(ConnectionString);

            if (svc.IsReady)
            {

                var attributeChangeHistoryReq = new RetrieveAttributeChangeHistoryRequest();

                attributeChangeHistoryReq.Target =
                    new EntityReference("incident", new Guid("0a9f62a8-90df-e311-9565-a45d36fc5fe8"));
                attributeChangeHistoryReq.AttributeLogicalName = "prioritycode";

                var attrChangeResponse = (RetrieveAttributeChangeHistoryResponse)svc.Execute(attributeChangeHistoryReq);
                var auditDetailCollection = attrChangeResponse.AuditDetailCollection;


                foreach (var auditDetails in auditDetailCollection.AuditDetails)
                {
                    // Type =  AttributeAuditDetail, AuditDetail, 
                    var type = auditDetails.GetType();

                    if (type == typeof(AttributeAuditDetail))
                    {
                        var attributeDetail = (AttributeAuditDetail)auditDetails;

                        var userName = attributeDetail.AuditRecord.GetAttributeValue<EntityReference>("userid").Name;
                        var operation = attributeDetail.AuditRecord.FormattedValues["operation"];
                        var action = attributeDetail.AuditRecord.FormattedValues["action"];
                        var createdOn = attributeDetail.AuditRecord.GetAttributeValue<DateTime>("createdon");
                        var newValue = attributeDetail.NewValue.FormattedValues["prioritycode"];
                        var oldValue = attributeDetail.OldValue?.FormattedValues["prioritycode"];

                    }
                }
            }

Check other posts on Audit

Hope it helps..

Advertisements