private void ChangesToToAction(RetrieveEntityChangesRequest req, Action <RetrieveEntityChangesResponse> action) { int pageCount = 1; while (true) { var results = _Service.Execute(req) as RetrieveEntityChangesResponse; try { action(results); if (results.EntityChanges.MoreRecords) { req.DataVersion = results.EntityChanges.DataToken; pageCount++; req.PageInfo = new PagingInfo(); req.PageInfo.Count = _DefaultPageSize; req.PageInfo.PageNumber = pageCount; req.PageInfo.PagingCookie = results.EntityChanges.PagingCookie; } else { break; } } catch (Exception ex) { //force retry of one record req.PageInfo.Count = 1; ChangesToToAction(req, action); } } }
public static List <EntityReference> RetrieveRemovedOrDeletedChanges(this IOrganizationService service, string entityName, ColumnSet columns, ref string dataToken) { var request = new RetrieveEntityChangesRequest { EntityName = entityName, DataVersion = dataToken, Columns = columns, PageInfo = new PagingInfo() { Count = 5000, PageNumber = 1, ReturnTotalRecordCount = false } }; var lists = new List <EntityReference>(); while (true) { var response = (RetrieveEntityChangesResponse)service.Execute(request); foreach (var change in response.EntityChanges.Changes) { if (change.Type == ChangeType.RemoveOrDeleted) { var changedItem = (RemovedOrDeletedItem)change; lists.Add(changedItem.RemovedItem); } } if (!response.EntityChanges.MoreRecords) { dataToken = response.EntityChanges.DataToken; break; } request.PageInfo.PageNumber++; request.PageInfo.PagingCookie = response.EntityChanges.PagingCookie; } return(lists); }
public static List <T> RetrieveNewOrUpdatedChanges <T>(this IOrganizationService service, string entityName, ref string dataToken) { var request = new RetrieveEntityChangesRequest(); request.EntityName = entityName; request.DataVersion = dataToken; request.Columns = new ColumnSet(true); request.PageInfo = new PagingInfo() { Count = 5000, PageNumber = 1, ReturnTotalRecordCount = false }; var lists = new List <T>(); while (true) { var response = (RetrieveEntityChangesResponse)service.Execute(request); foreach (var change in response.EntityChanges.Changes) { if (change.Type == ChangeType.NewOrUpdated) { var changedItem = (NewOrUpdatedItem)change; object[] args = new object[] { changedItem.NewOrUpdatedEntity }; lists.Add((T)Activator.CreateInstance(typeof(T), args)); } } if (!response.EntityChanges.MoreRecords) { dataToken = response.EntityChanges.DataToken; break; } request.PageInfo.PageNumber++; request.PageInfo.PagingCookie = response.EntityChanges.PagingCookie; } return(lists); }
public void ApplyChanges(IOrganizationService targetService, string entityName, ColumnSet columns, bool reprocessFailed = true) { RetrieveEntityChangesRequest changeRequest = new RetrieveEntityChangesRequest(); changeRequest.EntityName = entityName; changeRequest.Columns = columns; changeRequest.PageInfo = new PagingInfo() { Count = _DefaultPageSize, PageNumber = 1, ReturnTotalRecordCount = false }; var trackEntity = RetrieveTrackingEntity(targetService, entityName); if (trackEntity.Contains("ctccrm_datatoken")) { changeRequest.DataVersion = trackEntity.GetAttributeValue <string>("ctccrm_datatoken"); } CrmBulkServiceManager bulkMgr = new CrmBulkServiceManager(targetService); ChangesToToAction(changeRequest, (response) => { List <Entity> entitiesToUpSert = new List <Entity>(); List <EntityReference> entitiesToDelete = new List <EntityReference>(); PrepareUpsertDeleteLists(response, entitiesToUpSert, entitiesToDelete); trackEntity["ctccrm_datatoken"] = response.EntityChanges.DataToken; entitiesToUpSert.Add(trackEntity); try { bulkMgr.BulkUpsertAndDelete(entitiesToUpSert, entitiesToDelete, transactionMode: CTCBulkTransactionMode.Single); } catch (Exception ex) { if (changeRequest.PageInfo.Count == 1) { RecordFailedRecord(entityName, trackEntity, bulkMgr, entitiesToUpSert, ex); } else { throw ex; } } }); if (reprocessFailed) { ReProcessFailedForEntity(targetService, entityName, columns, bulkMgr); } }
/// <summary> /// Imports the ChangeTrackingSample solution. /// Creates 10 records in sample_book /// Initial sync and retrieves the 10 records. /// Updates the reords (Adds 10 new records and deletes one record and updates one record). /// Second sync to retrieve the changes since the last sync. /// </summary> /// <param name="serverConfig">Contains server connection information.</param> /// <param name="promptForDelete">When True, the user will be prompted to delete all /// created entities.</param> public void Run(ServerConnection.Configuration serverConfig, bool promptForDelete) { try { // Connect to the Organization service. // The using statement assures that the service proxy will be properly disposed. using (_serviceProxy = new OrganizationServiceProxy(serverConfig.OrganizationUri, serverConfig.HomeRealmUri, serverConfig.Credentials, serverConfig.DeviceCredentials)) { // This statement is required to enable early-bound type support. _serviceProxy.EnableProxyTypes(); // Check CRM version if (CheckCRMVersion()) { // Import the ChangeTrackingSample solution if it is not already installed. ImportChangeTrackingSolution(); // Wait for entity and key index to be active. WaitForEntityAndKeysToBeActive(_serviceProxy, _customBooksEntityName.ToLower()); // Create 10 demo records. CreateRequiredRecords(); string token; // Initialize page number. int pageNumber = 1; List <Entity> initialrecords = new List <Entity>(); // Retrieve records by using Change Tracking feature. RetrieveEntityChangesRequest request = new RetrieveEntityChangesRequest(); request.EntityName = _customBooksEntityName.ToLower(); request.Columns = new ColumnSet("sample_bookcode", "sample_name", "sample_author"); request.PageInfo = new PagingInfo() { Count = 5000, PageNumber = 1, ReturnTotalRecordCount = false }; // Initial Synchronization. Retrieves all records as well as token value. Console.WriteLine("Initial synchronization....retrieving all records."); while (true) { RetrieveEntityChangesResponse response = (RetrieveEntityChangesResponse)_serviceProxy.Execute(request); initialrecords.AddRange(response.EntityChanges.Changes.Select(x => (x as NewOrUpdatedItem).NewOrUpdatedEntity).ToArray()); initialrecords.ForEach(x => Console.WriteLine("initial record id:{0}", x.Id)); if (!response.EntityChanges.MoreRecords) { // Store token for later query token = response.EntityChanges.DataToken; break; } // Increment the page number to retrieve the next page. request.PageInfo.PageNumber++; // Set the paging cookie to the paging cookie returned from current results. request.PageInfo.PagingCookie = response.EntityChanges.PagingCookie; } // Display the initial records. // Do you like to view the records in browser? Add code. if (PromptForView()) { ViewEntityListInBrowser(); } // Delay 10 seconds, then create/update/delete records Console.WriteLine("waiting 10 seconds until next operation.."); Thread.Sleep(10000); // Add another 10 records, 1 update, and 1 delete. UpdateRecords(); // Second Synchronization. Basically do the same. // Reset paging pageNumber = 1; request.PageInfo.PageNumber = pageNumber; request.PageInfo.PagingCookie = null; // Assign token request.DataVersion = token; // Instantiate cache. List <Entity> updatedRecords = new List <Entity>(); List <EntityReference> deletedRecords = new List <EntityReference>(); while (true) { RetrieveEntityChangesResponse results = (RetrieveEntityChangesResponse)_serviceProxy.Execute(request); updatedRecords.AddRange(results.EntityChanges.Changes.Where(x => x.Type == ChangeType.NewOrUpdated).Select(x => (x as NewOrUpdatedItem).NewOrUpdatedEntity).ToArray()); deletedRecords.AddRange(results.EntityChanges.Changes.Where(x => x.Type == ChangeType.RemoveOrDeleted).Select(x => (x as RemovedOrDeletedItem).RemovedItem).ToArray()); if (!results.EntityChanges.MoreRecords) { break; } // Increment the page number to retrieve the next page. request.PageInfo.PageNumber++; // Set the paging cookie to the paging cookie returned from current results. request.PageInfo.PagingCookie = results.EntityChanges.PagingCookie; } // Do synchronizig work here. Console.WriteLine("Retrieving changes since the last sync...."); updatedRecords.ForEach(x => Console.WriteLine("new or updated record id:{0}!", x.Id)); deletedRecords.ForEach(x => Console.WriteLine("record id:{0} deleted!", x.Id)); // Prompt to view the records in the browser. if (PromptForView()) { Console.WriteLine("Retrieving the changes for the sample_book entity....."); ViewEntityListInBrowser(); } // Prompts to delete the ChangeTrackingSample managed solution. DeleteChangeTrackingSampleSolution(promptForDelete); } } } // Catch any service fault exceptions that Microsoft Dynamics CRM throws. catch (FaultException <Microsoft.Xrm.Sdk.OrganizationServiceFault> ) { // You can handle an exception here or pass it back to the calling method. throw; } }
[STAThread] // Added to support UX static void Main(string[] args) { CrmServiceClient service = null; try { service = SampleHelpers.Connect("Connect"); // Service implements IOrganizationService interface if (service.IsReady) { #region Sample Code ////////////////////////////////////////////// #region Set up SetUpSample(service); #endregion Set up #region Demonstrate /* * The Sample setup will import a ChangeTracking solution that contains * a sample_book entity that has an alternate key named sample_bookcode. * * 10 initial sample_book entity records are created so that changes to those * entities can be tracked. */ //To cache the RetrieveEntityChangesResponse.EntityChanges.DataToken value string dataVersionToken; //To cache information about the inital set of book records created. List <Entity> initialRecords = new List <Entity>(); //Retrieve initial records with tracked changes RetrieveEntityChangesRequest initialRequest = new RetrieveEntityChangesRequest() { EntityName = "sample_book", Columns = new ColumnSet("sample_bookcode", "sample_name", "sample_author"), PageInfo = new PagingInfo() { Count = 5000, PageNumber = 1, ReturnTotalRecordCount = false } }; // Initial Synchronization. Retrieves all records as well as token value. Console.WriteLine("Initial synchronization....retrieving all records."); RetrieveEntityChangesResponse initialResponse = (RetrieveEntityChangesResponse)service.Execute(initialRequest); //Cache the initial records for comparison. initialRecords.AddRange(initialResponse.EntityChanges.Changes.Select(x => (x as NewOrUpdatedItem).NewOrUpdatedEntity).ToArray()); // Store token for second query dataVersionToken = initialResponse.EntityChanges.DataToken; Console.WriteLine("Waiting 10 seconds until next operation.."); Thread.Sleep(10000); //Add another 10 records, 1 update, and 1 delete UpdateBookRecordsForSample(service); // Instantiate cache for changed and deleted records List <Entity> updatedRecords = new List <Entity>(); List <EntityReference> deletedRecords = new List <EntityReference>(); //Retrieve Changes since the initial records were created //The request is identical except it now has the DataVersion value set to the DataToken of the previous request. RetrieveEntityChangesRequest secondRequest = new RetrieveEntityChangesRequest() { EntityName = "sample_book", Columns = new ColumnSet("sample_bookcode", "sample_name", "sample_author"), PageInfo = new PagingInfo() { Count = 5000, PageNumber = 1, ReturnTotalRecordCount = false }, DataVersion = dataVersionToken }; //Get the results from the second request RetrieveEntityChangesResponse results = (RetrieveEntityChangesResponse)service.Execute(secondRequest); //Separate the results by type: NewOrUpdated or RemoveOrDeleted updatedRecords.AddRange(results.EntityChanges.Changes .Where(x => x.Type == ChangeType.NewOrUpdated) .Select(x => (x as NewOrUpdatedItem).NewOrUpdatedEntity).ToArray()); deletedRecords.AddRange(results.EntityChanges.Changes .Where(x => x.Type == ChangeType.RemoveOrDeleted) .Select(x => (x as RemovedOrDeletedItem).RemovedItem).ToArray()); //Test results Console.WriteLine("\nList of updated records:"); updatedRecords.ForEach(e => { Console.WriteLine(" name: {0}", e["sample_name"]); /* * Expected: * name: Demo Book 10 * name: Demo Book 11 * name: Demo Book 12 * name: Demo Book 13 * name: Demo Book 14 * name: Demo Book 15 * name: Demo Book 16 * name: Demo Book 17 * name: Demo Book 18 * name: Demo Book 19 * name: Demo Book 0 updated < Time record was updated > */ } ); Console.WriteLine("\nList of deleted record entity references:"); deletedRecords.ForEach(e => { Console.WriteLine(" LogicalName: {0} Id:{1}", e.LogicalName, e.Id); /* * Expected: * LogicalName: sample_book Id:< GUID of record that was deleted > */ } ); Console.WriteLine("\n"); #endregion Demonstrate #region Clean up // Provides option to delete the ChangeTracking solution CleanUpSample(service); #endregion Clean up ////////////////////////////////////////////// #endregion Sample Code Console.WriteLine("The sample completed successfully"); return; } else { const string UNABLE_TO_LOGIN_ERROR = "Unable to Login to Dynamics CRM"; if (service.LastCrmError.Equals(UNABLE_TO_LOGIN_ERROR)) { Console.WriteLine("Check the connection string values in cds/App.config."); throw new Exception(service.LastCrmError); } else { throw service.LastCrmException; } } } catch (Exception ex) { SampleHelpers.HandleException(ex); } finally { if (service != null) { service.Dispose(); } Console.WriteLine("Press <Enter> to exit."); Console.ReadLine(); } }
static void Main(string[] args) { CrmServiceClient client = new CrmServiceClient("Url=https://revforce.crm.dynamics.com; [email protected]; Password=Khunta96#; authtype=Office365"); IOrganizationService service = (IOrganizationService) client.OrganizationWebProxyClient != null ? (IOrganizationService)client.OrganizationWebProxyClient : (IOrganizationService)client.OrganizationServiceProxy; //Auto Number Field Setup CreateAttributeRequest widgetSerialNumberAttributeRequest = new CreateAttributeRequest { EntityName = "account", Attribute = new StringAttributeMetadata { //Define the format of the attribute AutoNumberFormat = "WID-{SEQNUM:5}-{RANDSTRING:6}-{DATETIMEUTC:yyyyMMddhhmmss}", LogicalName = "rev_autonumber", SchemaName = "rev_AutoNumber", RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None), MaxLength = 100, // The MaxLength defined for the string attribute must be greater than the length of the AutoNumberFormat value, that is, it should be able to fit in the generated value. DisplayName = new Label("Auto Number", 1033), Description = new Label("Unique Auto Incrementing field", 1033) } }; service.Execute(widgetSerialNumberAttributeRequest); Console.WriteLine("Field Added."); //Exporting Dynamics Data - RetrieveEntityChangesRequest RetrieveEntityChangesRequest req = new RetrieveEntityChangesRequest(); req.EntityName = "account"; req.Columns = new ColumnSet("name"); RetrieveEntityChangesResponse response = (RetrieveEntityChangesResponse)service.Execute(req); /* * //Specific Entity Key * Entity accont = new Entity("account", "accountnumber", "963963"); * accont.Attributes.Add("name", "ABCD Company"); * service.Update(accont); * * //Bulk Delete * string xml = @"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'> * <entity name='rev_policy'> * <attribute name='rev_policyid'/> * </entity> * </fetch>"; * * EntityCollection delCollection = service.RetrieveMultiple(new FetchExpression(xml)); * foreach(Entity policy in delCollection.Entities) * { * service.Delete("rev_policy", policy.Id); * } * * Contact c = new Contact() * { * FirstName = "", * LastName = "" * }; * * //Using LINQ * using(crmContext serviceContext = new crmContext(service)) * { * var accountsNames = from item in serviceContext.AccountSet * where item.Name == "ABYZ Company" * select item.Name; * * foreach (var aName in accountsNames) * { * Console.WriteLine(aName); * } * * var accountContacts = from account in serviceContext.AccountSet * join contacts in serviceContext.ContactSet * on account.Id equals contacts.AccountId.Id * where account.Name == "Adventure Works" * select new * { * contacts.FullName * }; * } * Contact c = new Contact() * { * } * * //Call Action rev_SendEmail * OrganizationRequest req = new OrganizationRequest("rev_sendemail"); * req.Parameters.Add("subject", "Welcome to CRM"); * req.Parameters.Add("Target", new EntityReference("contact", conGuid)); * OrganizationRequest response = service.Execute(req); * * Console.WriteLine(response.) * * */ /*string xml = @"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'> * <entity name='account'> * <attribute name='name' /> * <attribute name='primarycontactid' /> * <attribute name='telephone1' /> * <attribute name='accountid' /> * <order attribute='name' descending='false' /> * </entity> * </fetch>"; * * EntityCollection collection = service.RetrieveMultiple(new FetchExpression(xml)); * * foreach (Entity account in collection.Entities) * { * Console.WriteLine(account.Attributes["name"].ToString()); * }*/ //Console.Read(); // Create a contact record in Dynamics //Entity contact = new Entity("contact"); //contact.Attributes.Add("lastname", "Bartholomew"); //Guid contactGuid = service.Create(contact); //Entity incident = new Entity("incident"); //incident.Attributes.Add("title", "New Support Case"); //incident.Attributes.Add("customerid", new EntityReference("contact", contactGuid)); //service.Create(incident); Console.ReadLine(); }