private async Task <List <TableOperation> > BuildTableOperationUpsert(T entity)
        {
            var entityId        = EntityDefinition.GetIdValues(entity);
            var serializedField = EntityProperty.GeneratePropertyForByteArray(BSonConvert.SerializeObject(entity));
            var fields          = GetEntityFilterableFields(entity).ToList();
            var record          = GenerateRecordMainPartition(entity, serializedField, fields);

            List <TableOperation> operations = new List <TableOperation>
            {
                TableOperation.InsertOrReplace(record)
            };

            operations.AddRange(GeneratePersistPartitionData(entity, serializedField, fields)
                                .Select(TableOperation.InsertOrReplace));
            var idValue = string.Join(StorageQueryBuilder.PARTITION_FIELD_SEPARATOR,
                                      entityId.Select(StorageQueryBuilder.NormalizeStringValue));

            var old = await GetById(StorageQueryBuilder.GetTableKeyNormalizedValue(idValue)).ConfigureAwait(false);

            if (old != null)
            {
                var oldFields = GetEntityFilterableFields(old);
                IEnumerable <TableOperation> deleteOperations = GeneratePersistPartitionData(old, null, oldFields)
                                                                .Select(TableOperation.Delete)
                                                                .Where(d => !operations.Any(o =>
                                                                                            o.Entity.PartitionKey == d.Entity.PartitionKey && o.Entity.RowKey == d.Entity.RowKey))
                                                                .ToList();
                operations.AddRange(deleteOperations);
            }
            return(operations);
        }
        private IEnumerable <DynamicTableEntity> GeneratePersistPartitionData(T entity, EntityProperty serializedField, IEnumerable <KeyValuePair <string, EntityProperty> > fields)
        {
            List <DynamicTableEntity> result = new List <DynamicTableEntity>();

            foreach (var partition in EntityDefinition.GetPartitionsValues(entity))
            {
                var entityIdValues = EntityDefinition.GetIdValues(entity);
                var idString       = string.Join(StorageQueryBuilder.PARTITION_FIELD_SEPARATOR, entityIdValues.Select(StorageQueryBuilder.NormalizeStringValue));

                var partitionKey = StorageQueryBuilder.GetPartitionKeyValue(partition.Key, partition.Value);
                partitionKey = string.Join(StorageQueryBuilder.PARTITION_NAME_SEPARATOR, partition.Key, partitionKey);

                DynamicTableEntity record = new DynamicTableEntity(partitionKey, StorageQueryBuilder.GetTableKeyNormalizedValue(idString));
                record.ETag = "*";
                foreach (var field in fields)
                {
                    if (field.Value != null)
                    {
                        record.Properties.Add(field);
                    }
                }
                record.Properties.Add("Content", serializedField);
                result.Add(record);
            }

            return(result);
        }
示例#3
0
        private StorageQueryBuilder MatchPartitionAndFilters(List <StorageComparisonExpression> grp)
        {
            var partitions      = EntityDefinition.Partitions();
            var equalConditions = grp.Where(c => c.Operator == QueryComparisonOperator.Equal);


            StorageQueryBuilder candidatePartition = null;

            foreach (var partition in partitions)
            {
                StorageQueryBuilder current        = new StorageQueryBuilder(partition.Name, EntityDefinition);
                List <string>       selectedFields = new List <string>();
                foreach (var fld in partition.Expressions)
                {
                    var qryField = equalConditions.FirstOrDefault(f => f.EntityMember.MemberPath == fld.MemberPath);
                    if (qryField != null)
                    {
                        current.PartitionValues.Add(qryField.ConstantMember);
                        selectedFields.Add(qryField.EntityMember.MemberPath);
                    }
                    else
                    {
                        break;
                    }
                }
                current.Filters.AddRange(equalConditions.Where(c => selectedFields.All(s => s != c.EntityMember.MemberPath)));

                if (candidatePartition == null || candidatePartition.PartitionValues.Count < current.PartitionValues.Count)
                {
                    candidatePartition = current;
                }
            }

            candidatePartition.Filters.AddRange(grp.Where(c => c.Operator != QueryComparisonOperator.Equal));

            if (candidatePartition == null && !EntityDefinition.AllowTableScan)
            {
                throw new StorageInvalidOperationException($"Not found partitions for expression {String.Join(" And ", grp)}");
            }

            return(candidatePartition);
        }
        private DynamicTableEntity GenerateRecordMainPartition(T entity, EntityProperty serializedField, IEnumerable <KeyValuePair <string, EntityProperty> > fields)
        {
            var entityIdValues = EntityDefinition.GetIdValues(entity);
            var idString       = string.Join(StorageQueryBuilder.PARTITION_FIELD_SEPARATOR, entityIdValues.Select(StorageQueryBuilder.NormalizeStringValue));

            DynamicTableEntity record = new DynamicTableEntity(StorageQueryBuilder.MAIN_PARTITION_NAME, StorageQueryBuilder.GetTableKeyNormalizedValue(idString))
            {
                ETag = "*"
            };

            if (fields != null)
            {
                foreach (var field in fields)
                {
                    if (field.Value != null)
                    {
                        record.Properties.Add(field);
                    }
                }
            }

            record.Properties.Add("Content", serializedField);
            return(record);
        }