Monday, January 21, 2013

Execute Multiple Request (Rollup 12 - SDK 5.0.13)

Today, I have used the latest SDK 5.0.13 DLL to take advantage of "ExecuteMultipleRequest" for one of the bulk create and update scenario. This is really a nice SDK message for dealing with loads of data. It drastically improved the overall performance. This is mainly used for Bulk Creating, Updating and Deleting the records.
 
ExecuteMultipleRequest accepts an input collection of message Requests, executes each of the message requests in the order they appear in the input collection, and optionally returns a collection of Responses containing each message’s response or the error that occurred. Each message request in the input collection is processed in a separate database transaction.

@Developers, This is a very helpful message inclusion in the December 2012 Service updates (Rollup 12).

Here are the detailed steps with code snippet:

Create Scenario:
  • Create an Entity Collection object to hold multiple entity records.
  • Call the ExecuteMultipleRequest as in the below code snippet.
 
//Class level variable
private static EntityCollection _accountCollection = null;

//Create an instance of an entity collection
_accountCollection = new EntityCollection();

//Account object, You can use a for loop to add entity object to a collection.
for (int i = 0; i < 10; i++)
{
   var accountEntity = new Entity { LogicalName = "account" }; 
   accountEntity.Attributes.Add("name", "Test Account");

   /************************************************************/
   //accountId is a GUID of an account used only on UPDATE
     accountEntity.Attributes.Add("accountid", accountId);
   /************************************************************/

   accountEntity.Attributes.Add("accountnumber", "10010010");

   //Add an account entity to an entity collection
  _accountCollection.Entities.Add(accountEntity);
}

//Create
ExecuteCreateMultipleRequest(service, _accountCollection, tracer)

//Update : Note an entity collection records to have a GUID
ExecuteUpdateMultipleRequest(service, _accountCollection, tracer)


/// 
/// Latest SDK Message for Multiple record create
/// 
/// 
/// 
/// 
private static void ExecuteCreateMultipleRequest(IOrganizationService service, EntityCollection input, ITracingService tracer)
{
 // Create an ExecuteMultipleRequest object.
 var requestWithResults = new ExecuteMultipleRequest()
 {
  // Assign settings that define execution behavior: continue on error, return responses. 
  Settings = new ExecuteMultipleSettings()
  {
   ContinueOnError = false,
   ReturnResponses = true
  },
  // Create an empty organization request collection.
  Requests = new OrganizationRequestCollection()
 };

 tracer.Trace("Survey Entity Count" + input.Entities.Count);

 // Add a CreateRequest for each entity to the request collection.
 foreach (var entity in input.Entities)
 {
  var createRequest = new CreateRequest { Target = entity };
  requestWithResults.Requests.Add(createRequest);
 }

 // Execute all the requests in the request collection using a single web method call.
 var responseWithResults = (ExecuteMultipleResponse)service.Execute(requestWithResults);
}

/// 
/// Latest SDK Message for Multiple record update
/// 
/// 
/// 
/// 
private static void ExecuteUpdateMultipleRequest(IOrganizationService service, EntityCollection input, ITracingService tracer)
{
 // Create an ExecuteMultipleRequest object.
 var requestWithResults = new ExecuteMultipleRequest()
 {
  // Assign settings that define execution behavior: continue on error, return responses. 
  Settings = new ExecuteMultipleSettings()
  {
   ContinueOnError = false,
   ReturnResponses = true
  },
  // Create an empty organization request collection.
  Requests = new OrganizationRequestCollection()
 };

 tracer.Trace("Survey Entity Count" + input.Entities.Count);

 // Add a CreateRequest for each entity to the request collection.
 foreach (var entity in input.Entities)
 {
  var updateRequest = new UpdateRequest { Target = entity };
  requestWithResults.Requests.Add(updateRequest);
 }

 // Execute all the requests in the request collection using a single web method call.
 var responseWithResults = (ExecuteMultipleResponse)service.Execute(requestWithResults);
}
 
The same steps would also work on Update, Delete and any other CRM requet messages.
 
In order to use the above code, you should download the latest 2011SDK_5.0.13 SDK from the below link and use the microsoft.xrm.sdk.dll available in the SDK bin folder. 
 
 
You can use them from Custom .NET application and also, from the Plugins. The Plugin's would give you better performace than running it from a custom .net application.
 
Let me know, if you have any specific scenario's in Multiple records creation/Updation/deletion?
 
I truly love this feature, this opens up a lot of opportunities in building some custom components in CRM. Just great!!!
 
Hope this helps,
Chaitanya...

Thursday, January 10, 2013

Javascript Debugging

I know, this is known to many of us, just incase any one hits a roadblock on debugging the Javascript, here are some of the good links to get started.

Java Script Debugging with the Developer Tools (F12):
http://msdn.microsoft.com/en-us/library/dd565625(VS.85).aspx

CRM 2011 Debugging:
http://social.technet.microsoft.com/wiki/contents/articles/3…

CRM Javascript Debugging in IE8:
http://www.furnemont.eu/2010/06/how-to-series-easily-debug-y…

Thanks,
Chaitanya...

Tuesday, January 8, 2013

CRM 2011 SDK 5.0.13 Released.

 

Wednesday, October 17, 2012

MS CRM Online Video Library

Good one, have a look at the CRM online Video library.

Demo CRM Online

  
Hth,
Chaitanya...

Wednesday, June 27, 2012

Dealing with Dates in ODATA Endpoints.

I quote from MSDN:

When you retrieve records using the REST endpoint date values are returned as strings that use the format “\/Date()\/” where is the number of milliseconds since midnight January 1, 1970. For example: "\/Date(1311170400000)\/". All values returned from Microsoft Dynamics CRM represent the Universal Coordinated time (UTC) values.

Sample Code:

Note: In the below code sample "result" is the response from the ODATA querry.

//Retrieving the Date object as string
var stringDateValue = eval(result.CreatedOn).toString();               

Once the string date values are converted to Date objects you can use a variety of JScript methods to display the date as a string that can be displayed in a user interface .

var createdOn  = new Date(parseInt(stringDateValue.replace("/Date(", "").replace(")/", ""), 10)); 
createdOn = getODataLocalDateFilter(createdOn);

function getODataLocalDateFilter(date) {
//-- Description: For converting the date object to local time format
//-- You can also convert this to UTC Date format
//-- UTC Usage: getUTCMonth(), getUTCFullYear(), getUTCHours() ...
 var monthString;
 var rawMonth = (date.getMonth()+1).toString();
 if (rawMonth.length == 1) {
  monthString = "0" + rawMonth;
 }
 else
 { monthString = rawMonth; }
 var dateString;
 var rawDate = date.getUTCDate().toString();
 if (rawDate.length == 1) {
  dateString = "0" + rawDate;
 }
 else
 { dateString = rawDate; }

 var DateFilter = "";
 DateFilter += date.getFullYear() + "-";
 DateFilter += monthString + "-";
 DateFilter += dateString;
 DateFilter += " T" + date.getHours() + ":";
 DateFilter += date.getMinutes() + ":";
 DateFilter += date.getSeconds() + ":";
 DateFilter += date.getMilliseconds();

 return DateFilter;
}

Have fun working with ODATA!!

Tuesday, June 26, 2012

Updating the Owner in CRM.


For updating the Owner field programatically, we need to make use of the Assignrequest message. I have captured the sample code to update the Owner Id in CRM 4.0 and CRM 2011.

Updating the Owner Id in CRM 4.0:

Note: Plase, make sure to update the "ownerUpdatingEntity" with one you are trying to update. Also, Replace the "Entity_Name" with the name of the entity you are updating.

private static void AssignUser(CrmService service, Guid ownerId, Guid recordId)
{
 SecurityPrincipal assignee = new SecurityPrincipal();
 assignee.PrincipalId = ownerId;
 TargetOwnedDynamic ownerUpdatingEntity = new TargetOwnedDynamic();

 ownerUpdatingEntity.EntityId = recordId;
 ownerUpdatingEntity.EntityName = "Entity_Name";

 AssignRequest assign = new AssignRequest();

 assign.Assignee = assignee;
 assign.Target = ownerUpdatingEntity;

 AssignResponse assignResponse = (AssignResponse)service.Execute(assign);
}


Updating the Owner Id in CRM 2011:

Note: Please, make sure to replace the "Account.EntityLogicalName" with the right Entity in the below code.
 

private static void AssignUser(IOrganizationService service, Guid ownerId, Guid recordId)
{
 // Create the Request Object and Set the Request Object's Properties
 AssignRequest assign = new AssignRequest
 {
   Assignee = new EntityReference(SystemUser.EntityLogicalName, ownerId),
   Target = new EntityReference(Account.EntityLogicalName,recordId)
 };
 // Execute the Request
 service.Execute(assign);
}

Hope this helps!

 

Tuesday, June 5, 2012

Retrieve Plugin: MS CRM 2011

I was curious in retrieving the information from the context in Retrieve Plugin message. I realized that the context.InputParameters[“Target”], would return null/ throw exception in the retrieve plugin message.
  1.  To overcome that and to access the attribute collection through the context, here are the steps.
Plugin Configuration


2. The changes that needs to go in to the Plugin Retrieve message code. We need to make use of the OutputParameters collection.

            var orderRetrieve = (Entity) context.OutputParameters["BusinessEntity"];
            DateTime? date = null;
            if (orderRetrieve.Attributes.Contains("modifiedon"))
                date = (DateTime)orderRetrieve.Attributes["modifiedon"];



Also, couple of constraints, that I noticed in the Retrieve message plugin,
·         We cannot debug the Retrieve plugin by throwing an exception, in turn, we will not be able to see the tracing messages.
·         We cannot run plugin profiler to debug.

There is a way to handle the above constarints. will be blogging it on those topic soon...