예제 #1
0
 public bool ConfirmUpdate(int count, EntityMetadata meta)
 {
     return(_options.ConfirmUpdate(count, meta));
 }
예제 #2
0
파일: Query.cs 프로젝트: scubaracer/Sql4Cds
        /// <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");
        }
예제 #3
0
        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
                      };
            }
        }