Monday, February 13, 2012

Submit a Bulk Delete Job in Microsoft Dynamics CRM 2011 using C# or Jscript

This illustration shows how to submit a bulk delete job in Microsoft Dynamics CRM 2011 with BulkDeleteRequest.  This example will be given in Jscript (SOAP) and in C# (.NET).

NOTES: 

- You can schedule the job at regular intervals if desired using this request.  See the following link for details. http://msdn.microsoft.com/en-us/library/cc189846.aspx

- You can also define a start date and time for the job to occur.

- Lastly, this does not really act as a bulk delete request in the same sense as a bulk insert in SQL.  It submits an asynchronous job to the server that runs in the background but deletes the records one by one.  You will not really gain performance by this call versus a normal mass delete, but at least you won't have to babysit it.

Ok, here is what the code looks like!
First in C#:
BulkDeleteRequest req = new BulkDeleteRequest();
//send email to these receipients after job completes
req.ToRecipients = new Guid[] { new Guid("6E219F51-0310-4C4D-8C60-1C524E2BA7B3") };
//add cc recipients to the email here if desired
req.CCRecipients = new Guid[0];
req.JobName = "testbulkdeletejob";
req.SendEmailNotification = true;

req.RecurrencePattern = "";
//example of recurrence pattern 
   //int interval = 30;
   //string pattern = String.Format(System.Globalization.CultureInfo.InvariantCulture, "FREQ=DAILY;INTERVAL={0};", interval);
   //req.RecurrencePattern = pattern;
req.QuerySet = new QueryExpression[]
{
   new QueryExpression()
   {
       EntityName = "account",
       ColumnSet = new ColumnSet(true),
       Criteria = new FilterExpression
       {
           FilterOperator = LogicalOperator.And,
           Conditions = 
          {
              
              new ConditionExpression
              {
                  AttributeName = "name",
                  Operator = ConditionOperator.Equal,
                  Values = { "test account in code" }
              }
          }
       }
   }
};
BulkDeleteResponse resp = (BulkDeleteResponse)service.Execute(req);


If you need help instantiating a service object in .NET within a plugin check out this post:
http://mileyja.blogspot.com/2011/04/instantiating-service-object-within.html

Now here is the Jscript nicely formatted by the CRM 2011 SOAP formatter. Available at: http://crm2011soap.codeplex.com/

Now in Jscript


This example is asynchronous, if you want to learn how to make JScript SOAP calls synchronously please visit this posthttp://mileyja.blogspot.com/2011/07/using-jscript-to-access-soap-web.html


if (typeof (SDK) == "undefined")
   { SDK = { __namespace: true }; }
       //This will establish a more unique namespace for functions in this library. This will reduce the 
       // potential for functions to be overwritten due to a duplicate name when the library is loaded.
       SDK.SAMPLES = {
           _getServerUrl: function () {
               ///<summary>
               /// Returns the URL for the SOAP endpoint using the context information available in the form
               /// or HTML Web resource.
               ///</summary>
               var ServicePath = "/XRMServices/2011/Organization.svc/web";
               var serverUrl = "";
               if (typeof GetGlobalContext == "function") {
                   var context = GetGlobalContext();
                   serverUrl = context.getServerUrl();
               }
               else {
                   if (typeof Xrm.Page.context == "object") {
                         serverUrl = Xrm.Page.context.getServerUrl();
                   }
                   else
                   { throw new Error("Unable to access the server URL"); }
                   }
                  if (serverUrl.match(/\/$/)) {
                       serverUrl = serverUrl.substring(0, serverUrl.length - 1);
                   } 
                   return serverUrl + ServicePath;
               }, 
           BulkDeleteRequest: function () {
               var requestMain = ""
               requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
               requestMain += "  <s:Body>";
               requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
               requestMain += "      <request i:type=\"b:BulkDeleteRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">";
               requestMain += "        <a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <c:key>QuerySet</c:key>";
               requestMain += "            <c:value i:type=\"a:ArrayOfQueryExpression\">";
               requestMain += "              <a:QueryExpression>";
               requestMain += "                <a:ColumnSet>";
               requestMain += "                  <a:AllColumns>true</a:AllColumns>";
               requestMain += "                  <a:Columns xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\" />";
               requestMain += "                </a:ColumnSet>";
               requestMain += "                <a:Criteria>";
               requestMain += "                  <a:Conditions>";
               requestMain += "                    <a:ConditionExpression>";
               requestMain += "                      <a:AttributeName>name</a:AttributeName>";
               requestMain += "                      <a:Operator>Equal</a:Operator>";
               requestMain += "                      <a:Values xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">";
               requestMain += "                        <d:anyType i:type=\"e:string\" xmlns:e=\"http://www.w3.org/2001/XMLSchema\">test account in code</d:anyType>";
               requestMain += "                      </a:Values>";
               requestMain += "                    </a:ConditionExpression>";
               requestMain += "                  </a:Conditions>";
               requestMain += "                  <a:FilterOperator>And</a:FilterOperator>";
               requestMain += "                  <a:Filters />";
               requestMain += "                </a:Criteria>";
               requestMain += "                <a:Distinct>false</a:Distinct>";
               requestMain += "                <a:EntityName>account</a:EntityName>";
               requestMain += "                <a:LinkEntities />";
               requestMain += "                <a:Orders />";
               requestMain += "                <a:PageInfo>";
               requestMain += "                  <a:Count>0</a:Count>";
               requestMain += "                  <a:PageNumber>0</a:PageNumber>";
               requestMain += "                  <a:PagingCookie i:nil=\"true\" />";
               requestMain += "                  <a:ReturnTotalRecordCount>false</a:ReturnTotalRecordCount>";
               requestMain += "                </a:PageInfo>";
               requestMain += "                <a:NoLock>false</a:NoLock>";
               requestMain += "              </a:QueryExpression>";
               requestMain += "            </c:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <c:key>JobName</c:key>";
               requestMain += "            <c:value i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">testbulkdeletejob</c:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <c:key>SendEmailNotification</c:key>";
               requestMain += "            <c:value i:type=\"d:boolean\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">true</c:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <c:key>ToRecipients</c:key>";
               requestMain += "            <c:value i:type=\"d:ArrayOfguid\" xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">";
               requestMain += "              <d:guid>6e219f51-0310-4c4d-8c60-1c524e2ba7b3</d:guid>";
               requestMain += "            </c:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <c:key>CCRecipients</c:key>";
               requestMain += "            <c:value i:type=\"d:ArrayOfguid\" xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\" />";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <c:key>RecurrencePattern</c:key>";
               requestMain += "            <c:value i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\" />";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <c:key>StartDateTime</c:key>";
               requestMain += "            <c:value i:type=\"d:dateTime\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">0001-01-01T00:00:00</c:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>BulkDelete</a:RequestName>";
               requestMain += "      </request>";
               requestMain += "    </Execute>";
               requestMain += "  </s:Body>";
               requestMain += "</s:Envelope>";
               var req = new XMLHttpRequest();
               req.open("POST", SDK.SAMPLES._getServerUrl(), true)
               req.setRequestHeader("Accept", "application/xml, text/xml, */*");
               req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
               req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
               var successCallback = null;
               var errorCallback = null;
               req.onreadystatechange = function () { SDK.SAMPLES.BulkDeleteResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       BulkDeleteResponse: function (req, successCallback, errorCallback) {
               ///<summary>
               /// Recieves the assign response
               ///</summary>
               ///<param name="req" Type="XMLHttpRequest">
               /// The XMLHttpRequest response
               ///</param>
               ///<param name="successCallback" Type="Function">
               /// The function to perform when an successfult response is returned.
               /// For this message no data is returned so a success callback is not really necessary.
               ///</param>
               ///<param name="errorCallback" Type="Function">
               /// The function to perform when an error is returned.
               /// This function accepts a JScript error returned by the _getError function
               ///</param>
               if (req.readyState == 4) {
               if (req.status == 200) {
               if (successCallback != null)
               { successCallback(); }
               }
               else {
                   errorCallback(SDK.SAMPLES._getError(req.responseXML));
               }
           }
       },
       _getError: function (faultXml) {
           ///<summary>
           /// Parses the WCF fault returned in the event of an error.
           ///</summary>
           ///<param name="faultXml" Type="XML">
           /// The responseXML property of the XMLHttpRequest response.
           ///</param>
           var errorMessage = "Unknown Error (Unable to parse the fault)";
           if (typeof faultXml == "object") {
               try {
                   var bodyNode = faultXml.firstChild.firstChild;
                   //Retrieve the fault node
                   for (var i = 0; i < bodyNode.childNodes.length; i++) {
                       var node = bodyNode.childNodes[i];
                       //NOTE: This comparison does not handle the case where the XML namespace changes
                       if ("s:Fault" == node.nodeName) {
                       for (var j = 0; j < node.childNodes.length; j++) {
                           var faultStringNode = node.childNodes[j];
                           if ("faultstring" == faultStringNode.nodeName) {
                               errorMessage = faultStringNode.text;
                               break;
                           }
                       }
                       break;
                   }
               }
           }
           catch (e) { };
        }
        return new Error(errorMessage);
     },
 __namespace: true
};




To understand how to parse the response please review my post on using the DOM parser.
Now you can call the SDK.SAMPLES.BulkDeleteRequest function from your form jscript handler.

Thats all there is to it!
-

4 comments:

  1. Salesforce Admin Online Training - 21st Century Software ...
    www.21cssindia.com/courses/salesforce-admin-online-training-143.html
    Salesforce admin online training by 21cssindia the largest institute in providing online trainings in all technologies. Salesforce admin training, salesforce ...
    salesforce developer online training| salesforce developer ...
    www.21cssindia.com/.../salesforce-developer-online-training-144.html
    21cssindia provides Salesforce developer online training by real time Experts. Call us +91 9000444287 for online training and demo. Online Salesforce ...
    salesforce crm online training| salesforce crm training| call ...
    www.21cssindia.com/courses/salesforce-crm-online-training-212.html
    21cssindia provides Salesforce crm online training by real time Experts. Call us +91 9000444287 for online training and demo. Online Salesforce crm training ...

    ReplyDelete
  2. Thanks for this guide. I used to find Microsoft technology very hard to grasp but thanks to online training centers that I have learned SQL and many other Microsoft technologies.

    Best Regards,
    Crish Watson
    Pass Microsoft Certification Without Taking Exam

    ReplyDelete