Ejemplo n.º 1
0
        public Task <TResult> ExecuteUpdateAsync <TEntity, TResult>(MemberInfo memberInfo,
                                                                    IAzureStorageTableEntity <TEntity> updatedEntity,
                                                                    IAzureStorageTableEntity <TEntity> existingEntity,
                                                                    AzureTableDriverDynamic repository,
                                                                    Func <Func <Task>, TResult> onSuccessWithRollback,
                                                                    Func <TResult> onFailure)
        {
            var rowKey            = updatedEntity.RowKey;
            var valueUpdated      = updatedEntity.Entity;
            var dictionaryUpdated = updatedEntity.WriteEntity(null);
            var to                 = (IModifyAzureStorageTablePartitionKey)Activator.CreateInstance(this.To);
            var toPartitionKey     = to.GeneratePartitionKey(rowKey, valueUpdated, memberInfo);
            var typeWrapper        = new TypeWrapper(rowKey, toPartitionKey, dictionaryUpdated);
            var dictionaryExisting = existingEntity.WriteEntity(null);

            return(repository.InsertOrReplaceAsync <TEntity, TResult>(typeWrapper,
                                                                      (created, newEntity) => onSuccessWithRollback(
                                                                          () =>
            {
                if (created)
                {
                    return repository.DeleteAsync <TEntity, bool>(newEntity,
                                                                  () => true,
                                                                  () => true,
                                                                  () => false,
                                                                  (codes, why) => false);
                }
                var typeWrapperExisting = new TypeWrapper(rowKey, toPartitionKey, dictionaryExisting);
                return repository.ReplaceAsync <TEntity, bool>(typeWrapperExisting,
                                                               () => true);
            })));
        }
            public async Task <TResult> ExecuteUpdateModifiersAsync <TResult>(IAzureStorageTableEntity <EntityType> current,
                                                                              AzureTableDriverDynamic repository,
                                                                              Func <Func <Task>, TResult> onSuccessWithRollback,
                                                                              Func <MemberInfo[], TResult> onFailure)
            {
                var modifierResults = await typeof(EntityType)
                                      .GetPropertyOrFieldMembers()
                                      .Where(member => member.ContainsAttributeInterface <IModifyAzureStorageTableSave>())
                                      .SelectMany(memberInfo =>
                                                  memberInfo
                                                  .GetAttributesInterface <IModifyAzureStorageTableSave>()
                                                  .Select(
                                                      storageModifier =>
                {
                    return(storageModifier.ExecuteUpdateAsync(memberInfo,
                                                              this.RowKey, this.PartitionKey,
                                                              current.Entity, current.WriteEntity(null),
                                                              this.Entity, this.WriteEntity(null),
                                                              repository,
                                                              rollback => rollback.PairWithKey(true),
                                                              () => default(Func <Task>).PairWithKey(false)));
                }))
                                      .AsyncEnumerable()
                                      .ToArrayAsync();
                var rollbacks = modifierResults
                                .Where(kvp => kvp.Key)
                                .SelectValues(callback => callback());
                var didFail = modifierResults
                              .Where(kvp => !kvp.Key)
                              .Any();

                if (didFail)
                {
                    await Task.WhenAll(rollbacks);

                    return(onFailure(new MemberInfo[] { }));
                }

                return(onSuccessWithRollback(
                           () => Task.WhenAll(rollbacks)));
            }
        public async Task <TResult> ExecuteUpdateAsync <TEntity, TResult>(MemberInfo memberInfo,
                                                                          IAzureStorageTableEntity <TEntity> updatedEntity,
                                                                          IAzureStorageTableEntity <TEntity> existingEntity,
                                                                          AzureTableDriverDynamic repository,
                                                                          Func <Func <Task>, TResult> onSuccessWithRollback,
                                                                          Func <TResult> onFailure)
        {
            var valueExisting        = existingEntity.Entity;
            var existingRowKey       = valueExisting.StorageGetRowKey();
            var existingPartitionKey = valueExisting.StorageGetPartitionKey();

            var valueUpdated       = updatedEntity.Entity;
            var rowKeyRef          = updatedEntity.RowKey;
            var partitionKeyRef    = updatedEntity.PartitionKey;
            var dictionaryExisting = existingEntity.WriteEntity(null);

            if (IsIgnored(memberInfo, valueUpdated))
            {
                if (IsIgnored(memberInfo, valueExisting))
                {
                    return(onSuccessWithRollback(() => true.AsTask()));
                }
                var rollbackMaybeTask = await ExecuteDeleteAsync(memberInfo, rowKeyRef, partitionKeyRef,
                                                                 valueExisting, dictionaryExisting,
                                                                 repository,
                                                                 (rb) => rb,
                                                                 () => default);

                return(onSuccessWithRollback(rollbackMaybeTask));
            }

            var hashRowKey       = GetHashRowKey(memberInfo, valueUpdated, out string hashKeys);
            var hashPartitionKey = memberInfo.DeclaringType.Name;
            var tableName        = GetLookupTableName(memberInfo);

            return(await repository.UpdateOrCreateAsync <StorageLookupTable, TResult>(
                       hashRowKey, hashPartitionKey,
                       async (created, lookup, saveAsync) =>
            {
                if (!created)
                {
                    return onFailure();
                }

                async Task <Func <Task> > RollbackMaybeAsync()
                {
                    if (IsIgnored(memberInfo, valueExisting))
                    {
                        return default(Func <Task>);
                    }
                    return await ExecuteDeleteAsync(memberInfo, rowKeyRef, partitionKeyRef,
                                                    valueExisting, dictionaryExisting,
                                                    repository,
                                                    (rb) => rb,
                                                    () => default);
                }

                var rollbackMaybeTask = RollbackMaybeAsync();
                lookup.rawHash = hashKeys;     // Store raw hash to make the table easier to debug
                await saveAsync(lookup);
                var rollbackMaybe = await rollbackMaybeTask;

                Func <Task <bool> > rollback =
                    async() =>
                {
                    if (!rollbackMaybe.IsDefaultOrNull())
                    {
                        await rollbackMaybe();
                    }
                    return await repository.DeleteAsync <StorageLookupTable, bool>(hashRowKey, hashPartitionKey,
                                                                                   (discard) => true,
                                                                                   () => false,
                                                                                   onFailure: (codes, why) => false,
                                                                                   tableName: tableName);
                };
                return onSuccessWithRollback(rollback);
            },
                       tableName : tableName));
        }