public bool ConfirmUpdate(int count, EntityMetadata meta) { return(_options.ConfirmUpdate(count, meta)); }
/// <inheritdoc/> protected override object ExecuteInternal(IOrganizationService org, IAttributeMetadataCache metadata, IQueryExecutionOptions options) { if (options.Cancelled) { return(null); } // Check if the update is allowed if (options.BlockUpdateWithoutWhere && !FetchXml.Items.OfType <FetchEntityType>().Single().Items.OfType <filter>().Any()) { throw new InvalidOperationException("UPDATE without WHERE is blocked by your settings"); } // Get the records to update var count = 0; var entities = RetrieveAll(org, metadata, options).Entities; if (entities == null) { return(null); } var meta = metadata[EntityName]; // Check again that the update is allowed if (!options.ConfirmUpdate(entities.Count, meta)) { throw new OperationCanceledException("UPDATE cancelled by user"); } // Apply the update in batches ExecuteMultipleRequest multiple = null; foreach (var entity in entities) { if (options.Cancelled) { break; } var id = entity[IdColumn]; if (id is AliasedValue alias) { id = alias.Value; } var update = new Entity(EntityName); update.Id = (Guid)id; foreach (var attr in Updates) { update[attr.Key] = attr.Value(entity); } if (options.BatchSize == 1) { options.Progress($"Updating {meta.DisplayName?.UserLocalizedLabel?.Label} {count + 1:N0} of {entities.Count:N0}..."); org.Update(update); count++; } else { if (multiple == null) { multiple = new ExecuteMultipleRequest { Requests = new OrganizationRequestCollection(), Settings = new ExecuteMultipleSettings { ContinueOnError = false, ReturnResponses = false } }; } multiple.Requests.Add(new UpdateRequest { Target = update }); if (multiple.Requests.Count == options.BatchSize) { options.Progress($"Updating {meta.DisplayCollectionName?.UserLocalizedLabel?.Label} {count + 1:N0} - {count + multiple.Requests.Count:N0} of {entities.Count:N0}..."); var resp = (ExecuteMultipleResponse)org.Execute(multiple); if (resp.IsFaulted) { throw new ApplicationException($"Error updating {meta.DisplayCollectionName?.UserLocalizedLabel?.Label}"); } count += multiple.Requests.Count; multiple = null; } } } if (!options.Cancelled && multiple != null) { options.Progress($"Updating {meta.DisplayCollectionName?.UserLocalizedLabel?.Label} {count + 1:N0} - {count + multiple.Requests.Count:N0} of {entities.Count:N0}..."); var resp = (ExecuteMultipleResponse)org.Execute(multiple); if (resp.IsFaulted) { throw new ApplicationException($"Error updating {meta.DisplayCollectionName?.UserLocalizedLabel?.Label}"); } count += multiple.Requests.Count; } return($"{count:N0} {meta.DisplayCollectionName?.UserLocalizedLabel?.Label} updated"); }
public override string Execute(IDictionary <string, DataSource> dataSources, IQueryExecutionOptions options, IDictionary <string, Type> parameterTypes, IDictionary <string, object> parameterValues) { _executionCount++; try { if (!dataSources.TryGetValue(DataSource, out var dataSource)) { throw new QueryExecutionException("Missing datasource " + DataSource); } List <Entity> entities; EntityMetadata meta; Dictionary <string, AttributeMetadata> attributes; Dictionary <string, Func <Entity, object> > attributeAccessors; Func <Entity, object> primaryIdAccessor; using (_timer.Run()) { entities = GetDmlSourceEntities(dataSources, options, parameterTypes, parameterValues, out var schema); // Precompile mappings with type conversions meta = dataSource.Metadata[LogicalName]; attributes = meta.Attributes.ToDictionary(a => a.LogicalName); var dateTimeKind = options.UseLocalTimeZone ? DateTimeKind.Local : DateTimeKind.Utc; var fullMappings = new Dictionary <string, string>(ColumnMappings); fullMappings[meta.PrimaryIdAttribute] = PrimaryIdSource; attributeAccessors = CompileColumnMappings(meta, fullMappings, schema, attributes, dateTimeKind); primaryIdAccessor = attributeAccessors[meta.PrimaryIdAttribute]; } // Check again that the update is allowed. Don't count any UI interaction in the execution time if (options.Cancelled || !options.ConfirmUpdate(entities.Count, meta)) { throw new OperationCanceledException("UPDATE cancelled by user"); } using (_timer.Run()) { return(ExecuteDmlOperation( dataSource.Connection, options, entities, meta, entity => { var update = new Entity(LogicalName, (Guid)primaryIdAccessor(entity)); foreach (var attributeAccessor in attributeAccessors) { if (attributeAccessor.Key == meta.PrimaryIdAttribute) { continue; } var attr = attributes[attributeAccessor.Key]; if (!String.IsNullOrEmpty(attr.AttributeOf)) { continue; } var value = attributeAccessor.Value(entity); update[attr.LogicalName] = value; } return new UpdateRequest { Target = update }; }, new OperationNames { InProgressUppercase = "Updating", InProgressLowercase = "updating", CompletedLowercase = "updated" })); } } catch (QueryExecutionException ex) { if (ex.Node == null) { ex.Node = this; } throw; } catch (Exception ex) { throw new QueryExecutionException(ex.Message, ex) { Node = this }; } }