internal static IEnhancedOrgService GetConnection(string connectionString, bool noCache = false) { if (noCache) { ResetCache(connectionString); } var memKey = $"{ConnCacheMemKey}_{connectionString}"; lock (lockObj) { try { var service = CacheHelpers.GetFromMemCache <IEnhancedOrgService>(memKey); if (service != null) { return(service); } Status.Update($"Creating connection to CRM ... "); Status.Update($"Connection String:" + $" '{CrmHelpers.SecureConnectionString(connectionString)}'."); service = EnhancedServiceHelper.GetCachingPoolingService( new ServiceParams { ConnectionParams = new ConnectionParams { ConnectionString = connectionString }, PoolParams = new PoolParams { PoolSize = 5, DequeueTimeout = TimeSpan.FromSeconds(20) }, CachingParams = new CachingParams { CacheScope = CacheScope.Service }, OperationHistoryLimit = 1 }); CacheHelpers.AddToMemCache(memKey, service, TimeSpan.MaxValue); Status.Update($"Created connection."); return(service); } catch { CacheHelpers.RemoveFromMemCache(memKey); throw; } } }
protected override void ExecuteLogic() { codeActivity.CloneTemplateArg.Require(nameof(codeActivity.CloneTemplateArg)); var templateRef = executionContext.GetValue(codeActivity.CloneTemplateArg); var recordEntityName = executionContext.GetValue(codeActivity.RecordEntityNameArg); var recordId = executionContext.GetValue(codeActivity.RecordIdArg); recordEntityName.RequireNotEmpty(nameof(recordEntityName)); recordId.RequireNotEmpty(nameof(recordId)); log.Log($"Retrieving the template record '{templateRef.Id}' ..."); var template = service.Retrieve(templateRef.LogicalName, templateRef.Id, new ColumnSet(true)).ToEntity <CloneRecordTemplate>(); log.Log($"Retrieved the template record '{templateRef.Id}':'{template.Name}'."); CrmHelpers.LogAttributeValues(template.Attributes, template, log); Entity record = null; string[] fields = null; if (template.Fields.IsNotEmpty()) { fields = template.Fields.Split(','); log.Log($"Retrieving the record '{recordEntityName}':'{recordId}' ..."); record = service.Retrieve(recordEntityName, Guid.Parse(recordId), new ColumnSet(fields)); log.Log($"Retrieved the record '{recordEntityName}':'{recordId}'."); CrmHelpers.LogAttributeValues(record.Attributes, record, log); } var clonedRecord = new Entity(recordEntityName); if (record != null && fields != null) { log.Log("Copying field values ..."); var existingFields = fields.Where(f => record.Attributes.Contains(f)).ToArray(); log.Log(new LogEntry("Field list ...", information: string.Join(",", existingFields))); clonedRecord.Attributes.AddRange(existingFields.ToDictionary(f => f, f => record[f])); } if (template.CloneFlagField.IsNotEmpty()) { clonedRecord[template.CloneFlagField] = true; log.Log($"Set 'cloned' flag in field '{template.CloneFlagField}'."); } log.Log("Creating clone ..."); var id = service.Create(clonedRecord); log.Log($"Created clone: '{id}'."); executionContext.SetValue(codeActivity.ClonedRecordIdArg, id.ToString()); }
private static void StartExport() { System.Console.Clear(); System.Console.WriteLine("Starting Export:"); System.Console.WriteLine(); System.Console.Write("Please type the main entity logical name: "); var mainEntity = System.Console.ReadLine(); System.Console.WriteLine(); var filteredIds = CheckForFiltration(mainEntity); System.Console.Write($"Retrieveing {mainEntity} relationships"); ConsoleHelpers.PlayLoadingAnimation(); var customRelationships = CrmHelpers.GetCustomRelationships(_orgService, mainEntity, new[] { CrmHelpers.RelationType.ManyToManyRelationships }); ConsoleHelpers.StopLoadingAnimation(); ConsoleHelpers.WriteSuccess("Retrieved Relationships"); System.Console.WriteLine(); Export(customRelationships, filteredIds, mainEntity); }
public static IOrganizationService CreateCrmService(string connectionString) { CrmServiceClient service; lock (lockObject) { if (latestStringUsed != connectionString && !connectionString.ToLower().Contains("requirenewinstance")) { latestStringUsed = connectionString; connectionString = connectionString.Trim(';', ' '); connectionString += ";RequireNewInstance=true"; } service = new CrmServiceClient(connectionString); } var escapedString = Regex.Replace(connectionString, @"Password\s*?=.*?(?:;{0,1}$|;)", "Password=********;"); try { if (!string.IsNullOrEmpty(service.LastCrmError) || service.LastCrmException != null) { throw new ServiceActivationException( $"Can't create connection to: \"{escapedString}\" due to \"{service.LastCrmError}\""); } return(service); } catch (Exception ex) { var errorMessage = service.LastCrmError ?? (service.LastCrmException != null ? CrmHelpers.BuildExceptionMessage(service.LastCrmException) : null) ?? CrmHelpers.BuildExceptionMessage(ex); throw new ServiceActivationException($"Can't create connection to: \"{escapedString}\" due to\r\n{errorMessage}"); } }
public IOrganizationService CreateCrmService() { var service = new CrmServiceClient(parameters.ConnectionString); var escapedString = Regex.Replace(parameters.ConnectionString, @"Password\s*?=.*?(?:;{0,1}$|;)", "Password=********;"); try { if (!string.IsNullOrEmpty(service.LastCrmError) || service.LastCrmException != null) { throw new ServiceActivationException( $"Can't create connection to: \"{escapedString}\" due to \"{service.LastCrmError}\""); } return(service); } catch (Exception ex) { var errorMessage = service.LastCrmError ?? (service.LastCrmException != null ? CrmHelpers.BuildExceptionMessage(service.LastCrmException) : null) ?? CrmHelpers.BuildExceptionMessage(ex); throw new ServiceActivationException($"Can't create connection to: \"{escapedString}\" due to\r\n{errorMessage}"); } }
protected override void ExecuteLogic() { var xrmContext = new XrmServiceContext(Service) { MergeOption = MergeOption.NoTracking }; // get the triggering record var target = (Entity)Context.InputParameters["Target"]; Log.SetRegarding(Context.PrimaryEntityName, target.Id); var config = CrmHelpers.GetGenericConfig(Service, Context.OrganizationId.ToString()).ToEntity <CommonConfiguration>(); if (config.JobsPlatform != CommonConfiguration.JobsPlatformEnum.CRM) { throw new InvalidPluginExecutionException($"Cannot queue the job because target platform is not set to CRM" + $" (current: {config.JobsPlatform})."); } Log.Log("Fetching job records ..."); var jobRecordsQuery = from job in xrmContext.CustomJobSet where ((job.TargetDate == null || job.TargetDate < DateTime.UtcNow) && (job.StatusReason == CustomJob.StatusReasonEnum.Waiting || job.StatusReason == CustomJob.StatusReasonEnum.Retry)) || (job.ModifiedOn < DateTime.UtcNow.AddMinutes(-config.JobTimeout.GetValueOrDefault(20)) && (job.StatusReason == CustomJob.StatusReasonEnum.Running || job.StatusReason == CustomJob.StatusReasonEnum.Queued)) select new { job.CustomJobId, job.StatusReason }; var maxJobsPerRun = xrmContext.CustomJobEngineSet.Select(engine => engine.MaxJobsPerRun).FirstOrDefault(); if (maxJobsPerRun > 0) { jobRecordsQuery = jobRecordsQuery.Take(maxJobsPerRun.Value); } var jobRecords = jobRecordsQuery.ToList(); Log.Log($"Fetched job records '{jobRecords.Count}'."); Log.Log("Fetching parent job records ..."); var parentQuery = new FetchExpression( $@" <fetch no-lock='true'> <entity name='ldv_customjob'> <attribute name='ldv_customjobid' /> <attribute name='statuscode' /> <filter> <condition attribute='statuscode' operator='eq' value='{CustomJob.StatusReasonEnum.WaitingOnSubJobs}' /> <condition entityname='subjob' attribute='ldv_customjobid' operator='null' /> </filter> <link-entity name='ldv_customjob' from='ldv_parentjobid' to='ldv_customjobid' link-type='outer' alias='subjob' > <filter> <condition attribute='statecode' operator='eq' value='0' /> </filter> </link-entity> </entity> </fetch>"); var parentJobs = Service.RetrieveMultiple(parentQuery).Entities; Log.Log($"Fetched parent job records '{jobRecords.Count}'."); jobRecords = jobRecords .Union(parentJobs .Select(j => j.ToEntity <CustomJob>()) .Select(j => new { j.CustomJobId, j.StatusReason })) .Where(j => j.CustomJobId.HasValue).ToList(); Log.Log($"Fetched" + $" {jobRecords.Count(job => new [] { CustomJob.StatusReasonEnum.Queued, CustomJob.StatusReasonEnum.Running, CustomJob.StatusReasonEnum.WaitingOnSubJobs }.Contains(job.StatusReason.GetValueOrDefault()))}" + $" stalled job records."); if (jobRecords.Any()) { foreach (var jobRecord in jobRecords) { Service.Update( new CustomJob { Id = jobRecord.CustomJobId.GetValueOrDefault(), StatusReason = CustomJob.StatusReasonEnum.Queued, RunTrigger = new Random().Next(11111, 999999).ToString() }); } Log.Log(new LogEntry("Queue Information", information: jobRecords.Select(record => record.ToString()).Aggregate((r1, r2) => r1 + "\r\n" + r2))); } Log.Log("Fetching date-corrupted records ..."); var corruptJobs = (from job in xrmContext.CustomJobSet where job.TargetDate > new DateTime(2099, 1, 1) && job.StatusReason == CustomJob.StatusReasonEnum.Waiting && job.RecurrentJob == true select job.CustomJobId).ToArray().Where(id => id.HasValue).Select(id => id.GetValueOrDefault()).ToArray(); Log.Log($"Fetched {corruptJobs.Length} date-corrupted records."); if (corruptJobs.Any()) { Log.Log("Triggering recurrence recalculation of records ..."); foreach (var jobId in corruptJobs) { Service.Update( new CustomJob { Id = jobId, RecurrenceUpdatedTrigger = new Random().Next(111111, 99999999).ToString() }); Log.Log($"Triggered recurrence recalculation of '{jobId}'."); } Log.Log("Finished triggering recurrence recalculation of records."); } }
protected override void ExecuteLogic() { // get the triggering record var target = Target; NotificationMessage message = null; var isEnabled = CrmHelpers .GetGenericConfig(Service, Context.OrganizationId).ToEntity <CommonConfiguration>()? .NotificationsCentreEnabled == true; if (!isEnabled) { return; } switch (target.LogicalName) { case Email.EntityLogicalName: var email = target.ToEntity <Email>(); var body = email.Description; // no message if (string.IsNullOrEmpty(body)) { return; } if (body.Contains("<html>")) { var doc = new XmlDocument(); doc.LoadXml(body); body = doc.SelectSingleNode("body")?.InnerXml; } // html has no body to display if (string.IsNullOrEmpty(body)) { return; } var users = email.To .Select(e => e.Party) .Where(a => a.LogicalName == User.EntityLogicalName) .Select(a => new NotificationMessageUser { User = a.Id }).ToArray(); // no users to notify if (!users.Any()) { return; } message = new NotificationMessage { Title = email.Subject, Message = body, RegardingTypeCode = Email.EntityTypeCode, RegardingID = target.Id.ToString(), MessageUsers = users, NotificationSource = GlobalEnums.NotificationSource.Email }; break; case Task.EntityLogicalName: var task = target.ToEntity <Task>(); message = new NotificationMessage { Title = task.Subject, Message = task.Description, RegardingTypeCode = Task.EntityTypeCode, RegardingID = target.Id.ToString() }; var owner = task.Owner; switch (owner.LogicalName) { case User.EntityLogicalName: message.MessageUsers = new[] { new NotificationMessageUser { User = owner.Id } }; break; case Team.EntityLogicalName: message.MessageTeams = new[] { new NotificationMessageTeam { Team = owner.Id } }; break; } message.NotificationSource = GlobalEnums.NotificationSource.Task; break; } if (message != null) { message.StatusReason = NotificationMessage.StatusReasonEnum.Open; Service.Create(message); } }