serving the solutions day and night

Pages

Wednesday, September 4, 2013

MS Dynamics CRM - Bulk Delete using XRM

Import
MSDynamicsCRM2011.DNS.Entities
microsoft.crm.sdk.proxy
microsoft.xrm.client
microsoft.xrm.sdk
System.ServiceModel
System.Data.DataSetExtensions

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using GCEntity = BT.CRM2011.DNS.Entities;
using System.ServiceModel.Description;

namespace CRM.Audit.BulkDelete
{
    class Audit
    {
        private BulkDeleteResponse _bdRes;
        private Guid _bdResID;
        private Guid _bdGUID;
        private ConditionExpression _conExp;

//Delete Method
        public void Delete()
        {
            SystemJob(GCEntity.dns_audit.EntityLogicalName, "Audit Bulk Delete - Code", _conExp);
            Console.WriteLine("Audit Deleted");
            SystemJob(GCEntity.Contact.EntityLogicalName, "Contact Bulk Delete - Code", _conExp);
            Console.WriteLine("Contact Deleted");
            Console.ReadLine();
        }

//Create System JOB
        private void SystemJob(string entityName, string jobName, ConditionExpression conExp)
        {
            //var userRequest = new WhoAmIRequest();
            //var userResponse = (WhoAmIResponse)CRMServiceProxy.Execute(userRequest);
            //Guid currentUserId = userResponse.UserId;

            var dFilter = new FilterExpression();
            dFilter.Conditions.Add(conExp);

            var bdQuery = new QueryExpression
            {
                EntityName = entityName,
                Distinct = false,
                Criteria = dFilter
            };

            var bdReq = new BulkDeleteRequest
            {
                JobName = jobName,
                QuerySet = new[] { bdQuery },
                ToRecipients = new Guid[] {},
                CCRecipients = new Guid[] { },
                StartDateTime = DateTime.Now,
                RecurrencePattern = String.Empty
            };

            _bdRes = (BulkDeleteResponse)CRMServiceProxy.Execute(bdReq);
            _bdResID = _bdRes.JobId;

            var bQuery = new QueryByAttribute();
            bQuery.ColumnSet = new ColumnSet(true);
            bQuery.EntityName = GCEntity.BulkDeleteOperation.EntityLogicalName;
            bQuery.Attributes.Add("asyncoperationid");
            bQuery.Values.Add(_bdRes.JobId);
            var ec = CRMServiceProxy.RetrieveMultiple(bQuery);
            GCEntity.BulkDeleteOperation bdOpeCreated = null;
            var bOpeEnded = GCEntity.BulkDeleteOperationState.Completed;
            bdOpeCreated = RetrieveBulkDeleteOperation(bQuery, ec, bOpeEnded);
            _bdGUID = bdOpeCreated.Id;

            if (bdOpeCreated != null)
            {
                InspectBulkDeleteOperation(bdOpeCreated,bOpeEnded, false);

                if (bdOpeCreated.StateCode != GCEntity.BulkDeleteOperationState.Locked)
                {
                    DeleteRecords();
                }
            }
            else
            {
                Console.WriteLine("  The Bulk Delete Operation could not be retrieved.");
            }
        }

//Delete Records
        private void DeleteRecords()
        {
            // Delete the bulk delete operation so that it won't clutter the
            // database.
            CRMServiceProxy.Delete(
                GCEntity.BulkDeleteOperation.EntityLogicalName, _bdGUID);

            var asyncOperationEntity = CRMServiceProxy.Retrieve(
                GCEntity.AsyncOperation.EntityLogicalName, _bdResID,
                new ColumnSet("statecode", "asyncoperationid"));
            var asyncOperation = asyncOperationEntity.ToEntity<GCEntity.AsyncOperation>();

            if (asyncOperation.StateCode != GCEntity.AsyncOperationState.Completed)
            {
                // We have to update the AsyncOperation to be in a Completed state
                // before we can delete it.
                asyncOperation.StateCode = GCEntity.AsyncOperationState.Completed;
                CRMServiceProxy.Update(asyncOperation);
            }

            CRMServiceProxy.Delete(GCEntity.AsyncOperation.EntityLogicalName, _bdResID);

            Console.WriteLine("  The AsyncOperation and BulkDeleteOperation have been deleted.");
        }

        private void InspectBulkDeleteOperation(
            GCEntity.BulkDeleteOperation createdBulkDeleteOperation,
            GCEntity.BulkDeleteOperationState bulkOperationEnded,
            bool useRecurrence)
        {
            // Validate that the operation was completed.
            if (createdBulkDeleteOperation.StateCode != bulkOperationEnded)
            {
                // This will happen if it took longer than the polling time allowed
                // for this operation to complete.
                Console.WriteLine("  Completion of the Bulk Delete took longer than the polling time allotted.");
            }
            else if (createdBulkDeleteOperation.StatusCode.Value!= 30)
            {
                Console.WriteLine("  The Bulk Delete operation failed.");
            }
            else if (!useRecurrence)
            {
                // Check for the number of successful deletes.
                var successfulDeletes = createdBulkDeleteOperation.SuccessCount ?? 0;
                Console.WriteLine("  {0} records were successfully deleted",
                                  successfulDeletes);

                // Check for any failures that may have occurred during the bulk
                // delete operation.
                if (createdBulkDeleteOperation.FailureCount > 0)
                {
                    Console.WriteLine("  {0} records failed to be deleted:",
                                      createdBulkDeleteOperation.FailureCount);

                    // Query for all the failures.
                    var failureQuery = new QueryByAttribute();
                    failureQuery.ColumnSet = new ColumnSet(true);
                    failureQuery.EntityName = GCEntity.BulkDeleteFailure.EntityLogicalName;
                    failureQuery.Attributes.Add("bulkdeleteoperationid");
                    var bulkDeleteOperationId =
                        createdBulkDeleteOperation.BulkDeleteOperationId ?? Guid.Empty;
                    failureQuery.Values.Add(bulkDeleteOperationId);

                    // Retrieve the bulkdeletefailure objects.
                    EntityCollection entityCollection = CRMServiceProxy.RetrieveMultiple(
                        failureQuery);

                    // Examine each failure for information regarding the failure.
                    foreach (GCEntity.BulkDeleteFailure failureOperation in
                        entityCollection.Entities)
                    {
                        // Process failure information.
                        Console.WriteLine(String.Format(
                            "    {0}, {1}",
                            failureOperation.RegardingObjectId.Name,
                            failureOperation.RegardingObjectId.Id));
                    }
                }
            }
            else
            {
                // NOTE: If recurrence is used, we cannot reliably retrieve data
                // about the records that were deleted, since a sub-BulkDeleteOperation
                // is created by Microsoft Dynamics CRM that does not have any fields tying it back to the
                // Asynchronous operation or the BulkDeleteOperation. This makes it
                // unreliable to know which subprocess to retrieve.
                Console.WriteLine("  The recurring Bulk Delete Operation was created successfully.");
            }
        }

        private GCEntity.BulkDeleteOperation RetrieveBulkDeleteOperation(
            QueryByAttribute bulkQuery, EntityCollection entityCollection,
            GCEntity.BulkDeleteOperationState operationEndedStatus)
        {
            GCEntity.BulkDeleteOperation createdBulkDeleteOperation = null;
            // Monitor the async operation via polling until it is complete or max
            // polling time expires.
            const int ARBITRARY_MAX_POLLING_TIME = 60;
            int secondsTicker = ARBITRARY_MAX_POLLING_TIME;
            while (secondsTicker > 0)
            {
                // Make sure the async operation was retrieved.
                if (entityCollection.Entities.Count > 0)
                {
                    // Grab the one bulk operation that has been created.
                    createdBulkDeleteOperation =
                        (GCEntity.BulkDeleteOperation)entityCollection.Entities[0];

                    // Check the operation's state.
                    // NOTE: If a recurrence for the BulkDeleteOperation was
                    // specified, the state of the operation will be Suspended,
                    // not Completed, since the operation will run again in the
                    // future.
                    if (createdBulkDeleteOperation.StateCode !=
                        operationEndedStatus)
                    {
                        // The operation has not yet completed.  Wait a second for
                        // the status to change.
                        System.Threading.Thread.Sleep(1000);
                        secondsTicker--;

                        // Retrieve a fresh version of the bulk delete operation.
                        entityCollection = CRMServiceProxy.RetrieveMultiple(bulkQuery);
                    }
                    else
                    {
                        // Stop polling as the operation's state is now complete.
                        secondsTicker = 0;
                        Console.WriteLine(
                            "  The BulkDeleteOperation record has been retrieved.");
                    }
                }
                else
                {
                    // Wait a second for async operation to activate.
                    System.Threading.Thread.Sleep(1000);
                    secondsTicker--;

                    // Retrieve the entity again.
                    entityCollection = CRMServiceProxy.RetrieveMultiple(bulkQuery);
                }
            }
            return createdBulkDeleteOperation;
        }

        #region "credentials"
        public static OrganizationServiceProxy CRMServiceProxy
        {
            get
            {
                var uri = new Uri(System.Configuration.ConfigurationManager.AppSettings["OrganizationUri"]);

                //Authenticate using credentials of the logged in user;      
                var cntCredentials = new ClientCredentials();
                cntCredentials.Windows.ClientCredential.Domain = System.Configuration.ConfigurationManager.AppSettings["Domain"].ToString();
                cntCredentials.Windows.ClientCredential.UserName = System.Configuration.ConfigurationManager.AppSettings["UserName"].ToString();
                cntCredentials.Windows.ClientCredential.Password = System.Configuration.ConfigurationManager.AppSettings["Password"].ToString();
                //cntCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;

                var serviceProxy = new OrganizationServiceProxy(uri, null, cntCredentials, null);
                serviceProxy.EnableProxyTypes();

                return serviceProxy;
            }
        }
        #endregion "credentials"
    }
}