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); }
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); }