Retrieving related records in an N:N relationship using QueryExpression in CRM

Nice post on Retrieve from N:N relationship

Bernado Nguyen-Hoan's Blog - Coding Stories from an IT Mercenary

This post explains how the QueryExpression class can be used in conjunction with IOrganizationService.RetrieveMultiple() in CRM 2013 to retrieve related records for an entity in an N:N relationship. This is something that I could not find much documentation on, and it is not very straightforward – at least for someone starting out in CRM dev.

Scenario

I have two custom entities that have an N:N relationship between them: Course (logical name ng_course) and Subject (logical name ng_subject). The relationship is named ng_course_subject. The query that I need to write is to retrieve all Subjects assigned to a given Course.

Understanding QueryExpression and LinkEntity

The QueryExpression class is where you define your query. You can learn more about this class here: http://msdn.microsoft.com/en-us/library/microsoft.xrm.sdk.query.queryexpression(v=crm.6).aspx.

The key property of this class that enables us to retrieve the related records is the LinkEntities property, which is a collection of LinkEntity objects. Essentially LinkEntity

View original post 352 more words

Advertisements

The ‘distinct’ attribute is not declared error while trying to import solution in CRM 2016 (and earlier)

Hi,

Got this error while trying to import a managed solution in CRM 2016 Online.

During analysis we figured out that it was pointing to one of the charts created for System User Entity. It seemed like chart’s xml was modified after export and then imported. The xml definition of the chart contained distinct keyword.

Removing the distinct keyword from the Chart definition and importing it back and then importing the managed solution with this updated chart got imported without any error.

Hope it helps..

MB2-712 Certification: (Microsoft Dynamics CRM 2016 Customization and Configuration) – Revision Guide

Microsoft Dynamics 365 and Unified Service Desk

I have been completing a series of posts to help people prepare for the MB2-712 certification (Microsoft Dynamics CRM 2016 Customization and Configuration. Here is a collection of links to all of these posts. I hope these might serve as a useful revision aid for the MB2-712 exam.

The MB2-712 certification is not easy to study for. At least in my opinion! The reason being the scope of the exam. CRM is a large product and therefore customizing it is a big topic. But a fun topic and one you will really enjoy learning about.

Revision Notes (Introduction)

Introduction / Overview to MB2-712 Exam

Configure Microsoft Dynamics CRM

  • Configure Dynamics CRM settings
    • Configure auditing, document management and collaboration; configure business units; perform user management; configure email; manage teams
  • Manage Dynamics CRM security
    • Understand security roles; define permissions and privileges; configure access levels; configure security roles; assign security roles; work with…

View original post 341 more words

IPluginExecutionContext Depth is 2 in Create Plugin during Import of records in CRM 2015 (and earlier)

We had one of our plugins on Create of Opportunity however during the import of the Opportunity record it was not working properly. We had the Depth check in our plugin code to check for infinite loop as the same plugin was being used for Update also.

After some debugging we realized that Depth value is 2 instead of 1 during import.

To test this, we created a sample plugin for create of Test entity record and then imported the Test entity records.

As expected the import failed and we got our custom exception in it.

Hope this helps..

Sample code to update Access Mode of System User in C# (CRM 2016 or earlier)

Recently had a requirement to set Access Mode of around 500 users to Administrative from Read – Write. We wrote an on demand workflow for that. However, running that workflow on those 500 records in a batch of 100 records was causing them to stuck in waiting stage and we had to then manually resume those workflow instance. So we ended up writing a Console Application for that.


   QueryExpression queryExpression = new QueryExpression();
            queryExpression.EntityName = "systemuser";
            queryExpression.ColumnSet = new ColumnSet();
            queryExpression.ColumnSet.AddColumn("fullname");

            ConditionExpression conditionExpression1 = new ConditionExpression();
            conditionExpression1.AttributeName = "tk_businessarea";
            conditionExpression1.Values.Add("EE286698-AF08-E311-B55E-1CC1DE6DAA0B");
            conditionExpression1.Operator = ConditionOperator.Equal;

            ConditionExpression conditionExpression2 = new ConditionExpression();
            conditionExpression2.AttributeName = "isdisabled";
            conditionExpression2.Values.Add(false);
            conditionExpression2.Operator = ConditionOperator.Equal;

            // access mode ==> 0 --> Read Write and 1 --> Adminstrative
            ConditionExpression conditionExpression3 = new ConditionExpression();
            conditionExpression3.AttributeName = "accessmode";
            conditionExpression3.Values.Add(1);
            conditionExpression3.Operator = ConditionOperator.Equal;
            
            queryExpression.Criteria.AddCondition(conditionExpression1);
            queryExpression.Criteria.AddCondition(conditionExpression2);
            queryExpression.Criteria.AddCondition(conditionExpression3);

            queryExpression.Criteria.FilterOperator = LogicalOperator.And;

            EntityCollection entityColl = organizationProxy.RetrieveMultiple(queryExpression);
            foreach(var entity in entityColl.Entities)
            {
                Entity userEntity = new Entity("systemuser");
                userEntity.Id = entity.Id;
                userEntity.Attributes["accessmode"] = new OptionSetValue(0);
                organizationProxy.Update(userEntity);
            }

Hope it helps !!

Generic SQL error in CRM 2015 Online (and earlier)

Recently we were getting the Generic SQL Error in one of our Plugin which was registered in Create of Opportunity Line.

The scenario was that on qualifying the lead, opportunity was getting created and we had Async Plugin on Create of Opportunity that will create an Opportunity Line and had Sync Plugin on Create of Opportunity Line that was updating the parent Opportunity. This issue was occurring randomly.

We observed the following, that if both the Plugin are registered as Sync or Async the issue doesn’t occur. It also doesn’t occur if we have Opportunity Plugin on Create as Sync and the one on Opp. Line as Async.

The other way of solving the issue was to introduce delay before updating the Parent Opportunity from the child opportunity line create Plugin.

Hope this helps..

RetrieveMultiple performance on large datasets

Using TPL in CRM

Dreaming in CRM, PowerApps & Flow

EDIT (21/05/15): After DMing with @maustinjones, I have added stat for paged RetrieveMultiple as well. I have updated the post to include this.

EDIT (22/05/15): Updated post to reflect correct behaviour of no-lock when parallelising. Thanks @maustinjones. Please also refer to the follow up post -> http://dreamingincrm.com/2015/05/22/redux-retrievemultiple-on-large-datasets/ on why paging cookie, is the recommended approach.

MSCRM limits the maximum result size to 5000 records, when you use the RetrieveMultiple request. In order to overcome this and retrieve all the records, you’ll have to use paging. PFEDynamics team have also released an open-source library called PFE Xrm Core Library that utilises Task Parallel Library.

There is also ExecuteMultipleRequest that you can use to send bunch of requests in one go, and process the responses. This just wanted to document by findings, about the performance of these options:

  1. Just using Parallel.ForEach
  2. ExecuteMultipleRequest
  3. PFE Xrm Core
  4. Paged RetrieveMultiple

Run 1 (Batch…

View original post 529 more words

Sample code to close a quote as won using WinQuoteRequest in CRM 2016 (and earlier)

Just sharing a sample code to close quote as won through C#


WinQuoteRequest winQuoteRequest = new WinQuoteRequest();
Entity quoteClose = new Entity("quoteclose");
quoteClose.Attributes["quoteid"] = new EntityReference("quote", new Guid("015816C2-2F10-E611-8112-3863BB353ED0"));
quoteClose.Attributes["subject"] = "Quote Close" + DateTime.Now.ToString();
winQuoteRequest.QuoteClose = quoteClose;
winQuoteRequest.Status = new OptionSetValue(-1);
organizationProxy.Execute(winQuoteRequest);

Hope it helps..

Writing Scripts for SubGrids with CRM 2015 Update 1

crmcooking

With the release of CRM 2015 Update 1 we can write supported scripts to get information from the subgrids.

Before CRM Online 2015 Update 1 the only unique method for the subgrid control was refresh.

As an Xrm.Page.ui control, GridControl also has all the standard control methods: getControlType, Label methods, getParent,Visible methods, setFocus, and Notification methods as well as refresh

OnLoad event

Add event handlers to this event to run every time the subgrid refreshes. This includes when users sort the values by clicking the column headings. Use the GridControl.addOnLoad and GridControl.removeOnLoad methods to manage event handlers, usually in the form Onload event.

Example :

Xrm.Page.getControl("Contacts").addOnLoad(<functionname>);

getEntityName

Use this method to get the logical name of the entity data displayed in the grid.

getGrid

Use this method to get access to the Grid available in the GridControl.

getViewSelector

Returns the

View original post 203 more words

Set PartyList field To in Email in CRM 2015 (and earlier)

Sample code to set the PartyList field for Email Activity.


function setContact() {

var partlistData = new Array();
partlistData[0] = new Object();

// guid of the record
partlistData[0].id = "8B2AD82B-30D6-E511-811F-3863BB356F90";

// name of the record
partlistData[0].name = "Hugh Grant";

// entity schema name
partlistData[0].entityType = "contact";
Xrm.Page.getAttribute("to").setValue(partlistData)

}

Hope it helps..