Ejemplo n.º 1
0
 private static string GetAccurateCase(ItemStorageConfig config, string value)
 {
     return(config.LowerCamelCaseProperties ? Utils.ToLowerCamelCase(value) : value);
 }
Ejemplo n.º 2
0
        private static void PopulateConfigFromType(ItemStorageConfig config, ITypeInfo typeInfo)
        {
            DynamoDBTableAttribute tableAttribute = Utils.GetTableAttribute(typeInfo);

            if (tableAttribute == null)
            {
                config.TableName = typeInfo.Name;
            }
            else
            {
                if (string.IsNullOrEmpty(tableAttribute.TableName))
                {
                    throw new InvalidOperationException("DynamoDBTableAttribute.Table is empty or null");
                }
                config.TableName = tableAttribute.TableName;
                config.LowerCamelCaseProperties = tableAttribute.LowerCamelCaseProperties;
            }

            string tableAlias;

            if (AWSConfigs.DynamoDBConfig.Context.TableAliases.TryGetValue(config.TableName, out tableAlias))
            {
                config.TableName = tableAlias;
            }

            foreach (var member in typeInfo.GetMembers())
            {
                if (!ItemStorageConfig.IsValidMemberInfo(member))
                {
                    continue;
                }

                // prepare basic info
                PropertyStorage propertyStorage = new PropertyStorage(member);
                propertyStorage.AttributeName = GetAccurateCase(config, member.Name);

                // run through all DDB attributes
                List <DynamoDBAttribute> allAttributes = Utils.GetAttributes(member);
                foreach (var attribute in allAttributes)
                {
                    // filter out ignored properties
                    if (attribute is DynamoDBIgnoreAttribute)
                    {
                        propertyStorage.IsIgnored = true;
                    }

                    if (attribute is DynamoDBVersionAttribute)
                    {
                        propertyStorage.IsVersion = true;
                    }

                    DynamoDBPropertyAttribute propertyAttribute = attribute as DynamoDBPropertyAttribute;
                    if (propertyAttribute != null)
                    {
                        if (!string.IsNullOrEmpty(propertyAttribute.AttributeName))
                        {
                            propertyStorage.AttributeName = GetAccurateCase(config, propertyAttribute.AttributeName);
                        }

                        if (propertyAttribute.Converter != null)
                        {
                            propertyStorage.ConverterType = propertyAttribute.Converter;
                        }

                        if (propertyAttribute is DynamoDBHashKeyAttribute)
                        {
                            var gsiHashAttribute = propertyAttribute as DynamoDBGlobalSecondaryIndexHashKeyAttribute;
                            if (gsiHashAttribute != null)
                            {
                                propertyStorage.IsGSIHashKey = true;
                                propertyStorage.AddIndex(gsiHashAttribute);
                            }
                            else
                            {
                                propertyStorage.IsHashKey = true;
                            }
                        }
                        if (propertyAttribute is DynamoDBRangeKeyAttribute)
                        {
                            var gsiRangeAttribute = propertyAttribute as DynamoDBGlobalSecondaryIndexRangeKeyAttribute;
                            if (gsiRangeAttribute != null)
                            {
                                propertyStorage.IsGSIRangeKey = true;
                                propertyStorage.AddIndex(gsiRangeAttribute);
                            }
                            else
                            {
                                propertyStorage.IsRangeKey = true;
                            }
                        }

                        DynamoDBLocalSecondaryIndexRangeKeyAttribute lsiRangeKeyAttribute = propertyAttribute as DynamoDBLocalSecondaryIndexRangeKeyAttribute;
                        if (lsiRangeKeyAttribute != null)
                        {
                            propertyStorage.IsLSIRangeKey = true;
                            propertyStorage.AddIndex(lsiRangeKeyAttribute);
                        }
                    }
                }

                config.Properties.Add(propertyStorage);
            }
        }
Ejemplo n.º 3
0
 public ItemStorage(ItemStorageConfig storageConfig)
 {
     Document = new Document();
     Config   = storageConfig;
 }
Ejemplo n.º 4
0
 public ConfigTableCache(ItemStorageConfig baseTypeConfig)
 {
     BaseTypeConfig = baseTypeConfig;
     BaseTableName  = BaseTypeConfig.TableName;
     Cache          = new Dictionary <string, ItemStorageConfig>(StringComparer.Ordinal);
 }
Ejemplo n.º 5
0
 private static void ValidateConfigAgainstTable(ItemStorageConfig config, Table table)
 {
     CompareKeys(config, table, table.HashKeys, config.HashKeyPropertyNames, "hash");
     CompareKeys(config, table, table.RangeKeys, config.RangeKeyPropertyNames, "range");
 }
Ejemplo n.º 6
0
        internal static ItemStorageConfig CreateStorageConfig(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            var typeWrapper          = TypeFactory.GetTypeInfo(type);
            ItemStorageConfig config = new ItemStorageConfig(type);

            DynamoDBTableAttribute tableAttribute = Utils.GetTableAttribute(type);

            if (tableAttribute == null || string.IsNullOrEmpty(tableAttribute.TableName))
            {
                throw new InvalidOperationException("No DynamoDBTableAttribute on type");
            }

            if (string.IsNullOrEmpty(tableAttribute.TableName))
            {
                throw new InvalidOperationException("DynamoDBTableAttribute.Table is empty or null");
            }
            config.TableName = tableAttribute.TableName;
            config.LowerCamelCaseProperties = tableAttribute.LowerCamelCaseProperties;

            foreach (var member in typeWrapper.GetMembers())
            {
                // filter out non-fields and non-properties
                if (!(member is FieldInfo || member is PropertyInfo))
                {
                    continue;
                }

                // filter out properties that aren't both read and write
                if (!Utils.IsReadWrite(member))
                {
                    continue;
                }

                // prepare basic info
                Type            memberType      = Utils.GetType(member);
                string          attributeName   = GetAccurateCase(config, member.Name);
                string          propertyName    = member.Name;
                PropertyStorage propertyStorage = new PropertyStorage(member, memberType);

                // run through all DDB attributes
                bool ignorePresent = false;
                var  allAttributes = Utils.GetAttributes(member);
                foreach (var attribute in allAttributes)
                {
                    // filter out ignored properties
                    if (attribute is DynamoDBIgnoreAttribute)
                    {
                        ignorePresent |= true;
                    }

                    // if ignore attribute is present, ignore other attributes
                    if (ignorePresent)
                    {
                        continue;
                    }

                    if (attribute is DynamoDBVersionAttribute)
                    {
                        Utils.ValidateVersionType(memberType);    // no conversion is possible, so type must be a nullable primitive

                        propertyStorage.IsVersion = true;
                    }

                    DynamoDBPropertyAttribute propertyAttribute = attribute as DynamoDBPropertyAttribute;
                    if (propertyAttribute != null)
                    {
                        if (!string.IsNullOrEmpty(propertyAttribute.AttributeName))
                        {
                            attributeName = GetAccurateCase(config, propertyAttribute.AttributeName);
                        }

                        if (propertyAttribute is DynamoDBHashKeyAttribute)
                        {
                            if (propertyAttribute.Converter == null && !Utils.IsPrimitive(memberType))
                            {
                                throw new InvalidOperationException("Hash key " + propertyName + " must be of primitive type");
                            }

                            if (propertyAttribute is DynamoDBGlobalSecondaryIndexHashKeyAttribute)
                            {
                                propertyStorage.IsGSIHashKey = true;
                                var gsiHashAttribute = propertyAttribute as DynamoDBGlobalSecondaryIndexHashKeyAttribute;
                                if (gsiHashAttribute.IndexNames == null || gsiHashAttribute.IndexNames.Length == 0)
                                {
                                    throw new InvalidOperationException("Global Secondary Index must not be null or empty");
                                }
                                propertyStorage.Indexes.AddRange(gsiHashAttribute.IndexNames);
                                AddGSIConfigs(config, gsiHashAttribute.IndexNames, propertyName, true);
                            }
                            else
                            {
                                propertyStorage.IsHashKey = true;
                            }
                        }
                        if (propertyAttribute is DynamoDBRangeKeyAttribute)
                        {
                            if (propertyAttribute.Converter == null && !Utils.IsPrimitive(memberType))
                            {
                                throw new InvalidOperationException("Range key " + propertyName + " must be of primitive type");
                            }

                            if (propertyAttribute is DynamoDBGlobalSecondaryIndexRangeKeyAttribute)
                            {
                                propertyStorage.IsGSIRangeKey = true;
                                var gsiRangeAttribute = propertyAttribute as DynamoDBGlobalSecondaryIndexRangeKeyAttribute;
                                if (gsiRangeAttribute.IndexNames == null || gsiRangeAttribute.IndexNames.Length == 0)
                                {
                                    throw new InvalidOperationException("Global Secondary Index must not be null or empty");
                                }
                                propertyStorage.Indexes.AddRange(gsiRangeAttribute.IndexNames);
                                AddGSIConfigs(config, gsiRangeAttribute.IndexNames, propertyName, false);
                            }
                            else
                            {
                                propertyStorage.IsRangeKey = true;
                            }
                        }
                        if (propertyAttribute is DynamoDBLocalSecondaryIndexRangeKeyAttribute)
                        {
                            DynamoDBLocalSecondaryIndexRangeKeyAttribute lsiRangeKeyAttribute = propertyAttribute as DynamoDBLocalSecondaryIndexRangeKeyAttribute;
                            if (lsiRangeKeyAttribute.IndexNames == null || lsiRangeKeyAttribute.IndexNames.Length == 0)
                            {
                                throw new InvalidOperationException("Local Secondary Index must not be null or empty");
                            }
                            propertyStorage.Indexes.AddRange(lsiRangeKeyAttribute.IndexNames);
                            propertyStorage.IsLSIRangeKey = true;

                            foreach (var index in lsiRangeKeyAttribute.IndexNames)
                            {
                                List <string> properties;
                                if (!config.IndexNameToLSIRangePropertiesMapping.TryGetValue(index, out properties))
                                {
                                    properties = new List <string>();
                                    config.IndexNameToLSIRangePropertiesMapping[index] = properties;
                                }
                                properties.Add(propertyName);
                            }
                        }

                        if (propertyAttribute.Converter != null)
                        {
                            if (!Utils.CanInstantiate(propertyAttribute.Converter) || !Utils.ImplementsInterface(propertyAttribute.Converter, typeof(IPropertyConverter)))
                            {
                                throw new InvalidOperationException("Converter for " + propertyName + " must be instantiable with no parameters and must implement IPropertyConverter");
                            }

                            propertyStorage.Converter = Utils.Instantiate(propertyAttribute.Converter) as IPropertyConverter;
                        }
                    }
                }

                propertyStorage.PropertyName  = propertyName;
                propertyStorage.AttributeName = attributeName;

                // only add property storage if no ignore attribute was present
                if (!ignorePresent)
                {
                    config.AddPropertyStorage(propertyStorage);
                }
            }

            if (config.HashKeyPropertyNames.Count == 0)
            {
                throw new InvalidOperationException("No hash key configured for type " + type.FullName);
            }

            return(config);
        }
        private static QueryFilter ComposeQueryFilter(object hashKeyValue, IEnumerable <QueryCondition> conditions, ItemStorageConfig storageConfig, out List <string> indexNames)
        {
            if (hashKeyValue == null)
            {
                throw new ArgumentNullException("hashKeyValue");
            }

            string        hashKeyProperty = storageConfig.HashKeyPropertyNames[0];
            DynamoDBEntry hashKeyEntry    = ValueToDynamoDBEntry(hashKeyProperty, hashKeyValue, storageConfig);

            if (hashKeyEntry == null)
            {
                throw new InvalidOperationException("Unable to convert hash key value for property " + hashKeyProperty);
            }
            string   hashAttributeName = storageConfig.GetPropertyStorage(hashKeyProperty).AttributeName;
            Document hashKey           = new Document();

            hashKey[hashAttributeName] = hashKeyEntry;

            return(ComposeQueryFilterHelper(hashKey, conditions, storageConfig, out indexNames));
        }
Ejemplo n.º 8
0
        private ContextSearch ConvertQueryByValue <T>(object hashKeyValue, IEnumerable <QueryCondition> conditions, DynamoDBOperationConfig operationConfig, ItemStorageConfig storageConfig = null)
        {
            DynamoDBFlatConfig flatConfig = new DynamoDBFlatConfig(operationConfig, Config);

            if (storageConfig == null)
            {
                storageConfig = StorageConfigCache.GetConfig <T>(flatConfig);
            }

            List <string> indexNames;
            QueryFilter   filter = ComposeQueryFilter(flatConfig, hashKeyValue, conditions, storageConfig, out indexNames);

            return(ConvertQueryHelper <T>(flatConfig, storageConfig, filter, indexNames));
        }
        internal static ItemStorage ObjectToItemStorage <T>(T toStore, bool keysOnly, bool ignoreNullValues, ItemStorageConfig config)
        {
            ItemStorage storage = new ItemStorage(config);

            PopulateItemStorage(toStore, keysOnly, ignoreNullValues, storage);
            return(storage);
        }
        // Query/Scan building
        private static ScanFilter ComposeScanFilter(IEnumerable <ScanCondition> conditions, ItemStorageConfig storageConfig)
        {
            ScanFilter filter = new ScanFilter();

            foreach (var condition in conditions)
            {
                PropertyStorage       propertyStorage = storageConfig.GetPropertyStorage(condition.PropertyName);
                List <AttributeValue> attributeValues = new List <AttributeValue>();
                foreach (var value in condition.Values)
                {
                    var entry = ToDynamoDBEntry(propertyStorage, value, true);
                    if (entry == null)
                    {
                        throw new InvalidOperationException(
                                  string.Format("Unable to convert value corresponding to property [{0}] to DynamoDB representation", condition.PropertyName));
                    }

                    AttributeValue nativeValue = entry.ConvertToAttributeValue();
                    if (nativeValue != null)
                    {
                        attributeValues.Add(nativeValue);
                    }
                }
                filter.AddCondition(propertyStorage.AttributeName, condition.Operator, attributeValues);
            }
            return(filter);
        }
        // This method composes the query filter and determines the possible indexes that the filter
        // may be used against. In the case where the condition property is also a RANGE key on the
        // table and not just on LSI/GSI, the potential index will be "" (absent).
        private QueryFilter ComposeQueryFilterHelper(
            DynamoDBFlatConfig currentConfig,
            Document hashKey,
            IEnumerable <QueryCondition> conditions,
            ItemStorageConfig storageConfig,
            out List <string> indexNames)
        {
            if (hashKey == null)
            {
                throw new ArgumentNullException("hashKey");
            }

            if (storageConfig.HashKeyPropertyNames.Count != 1)
            {
                throw new InvalidOperationException("Must have one hash key defined for the table " + storageConfig.TableName);
            }
            if (storageConfig.RangeKeyPropertyNames.Count != 1 && storageConfig.IndexNameToGSIMapping.Count == 0)
            {
                throw new InvalidOperationException("Must have one range key or a GSI index defined for the table " + storageConfig.TableName);
            }

            QueryFilter filter = new QueryFilter();

            // Configure hash-key equality condition
            string hashKeyProperty = storageConfig.HashKeyPropertyNames[0];

            hashKeyProperty = storageConfig.GetCorrectHashKeyProperty(currentConfig, hashKeyProperty);
            PropertyStorage propertyStorage = storageConfig.GetPropertyStorage(hashKeyProperty);
            string          attributeName   = propertyStorage.AttributeName;
            DynamoDBEntry   hashValue       = hashKey[attributeName];

            filter.AddCondition(attributeName, QueryOperator.Equal, hashValue);

            indexNames = new List <string>();
            if (conditions != null)
            {
                foreach (QueryCondition condition in conditions)
                {
                    object[]        conditionValues   = condition.Values;
                    PropertyStorage conditionProperty = storageConfig.GetPropertyStorage(condition.PropertyName);
                    if (conditionProperty.IsLSIRangeKey || conditionProperty.IsGSIKey)
                    {
                        indexNames.AddRange(conditionProperty.IndexNames);
                    }
                    if (conditionProperty.IsRangeKey)
                    {
                        indexNames.Add(NO_INDEX);
                    }
                    List <AttributeValue> attributeValues = ConvertConditionValues(conditionValues, conditionProperty, currentConfig);
                    filter.AddCondition(conditionProperty.AttributeName, condition.Operator, attributeValues);
                }
            }
            if (currentConfig.QueryFilter != null)
            {
                foreach (ScanCondition condition in currentConfig.QueryFilter)
                {
                    object[]              conditionValues   = condition.Values;
                    PropertyStorage       conditionProperty = storageConfig.GetPropertyStorage(condition.PropertyName);
                    List <AttributeValue> attributeValues   = ConvertConditionValues(conditionValues, conditionProperty, currentConfig, canReturnScalarInsteadOfList: true);
                    filter.AddCondition(conditionProperty.AttributeName, condition.Operator, attributeValues);
                }
            }
            return(filter);
        }
Ejemplo n.º 12
0
        private async Task <T> LoadHelperAsync <T>(Key key, DynamoDBFlatConfig flatConfig, ItemStorageConfig storageConfig, CancellationToken cancellationToken)
        {
            GetItemOperationConfig getConfig = new GetItemOperationConfig
            {
                ConsistentRead  = flatConfig.ConsistentRead.Value,
                AttributesToGet = storageConfig.AttributesToGet
            };

            Table       table   = GetTargetTable(storageConfig, flatConfig);
            ItemStorage storage = new ItemStorage(storageConfig);

            storage.Document = await table.GetItemHelperAsync(key, getConfig, cancellationToken).ConfigureAwait(false);

            T instance = DocumentToObject <T>(storage, flatConfig);

            return(instance);
        }
Ejemplo n.º 13
0
 public ItemStorage(ItemStorageConfig storageConfig)
 {
     Document         = new Document();
     Config           = storageConfig;
     ConvertedObjects = new HashSet <object>();
 }
Ejemplo n.º 14
0
        private static void PopulateConfigFromTable(ItemStorageConfig config, Table table)
        {
            PropertyStorage property;

            // keys
            foreach (var key in table.Keys)
            {
                var attributeName  = key.Key;
                var keyDescription = key.Value;

                if (GetExistingProperty(config, attributeName, false, out property))
                {
                    // validate against table
                    if (property.IsKey)
                    {
                        ValidateProperty(property.IsHashKey == keyDescription.IsHash,
                                         property.PropertyName, "Property key definition must match table key definition");
                    }
                }

                // populate property
                if (keyDescription.IsHash)
                {
                    property.IsHashKey = true;
                }
                else
                {
                    property.IsRangeKey = true;
                }
            }

            foreach (var kvp in table.GlobalSecondaryIndexes)
            {
                string indexName = kvp.Key;
                var    gsi       = kvp.Value;

                foreach (var element in gsi.KeySchema)
                {
                    string attributeName = element.AttributeName;
                    bool   isHashKey     = element.KeyType == KeyType.HASH;

                    GetExistingProperty(config, attributeName, true, out property);
                    if (property != null)
                    {
                        property.AddGsiIndex(isHashKey, attributeName, indexName);
                    }
                }
            }

            foreach (var kvp in table.LocalSecondaryIndexes)
            {
                string indexName = kvp.Key;
                var    lsi       = kvp.Value;

                foreach (var element in lsi.KeySchema)
                {
                    string attributeName = element.AttributeName;
                    bool   isHashKey     = element.KeyType == KeyType.HASH;

                    // only add for range keys
                    if (!isHashKey)
                    {
                        GetExistingProperty(config, attributeName, true, out property);
                        if (property != null)
                        {
                            property.AddLsiIndex(attributeName, indexName);
                        }
                    }
                }
            }
        }
        private static QueryFilter ComposeQueryFilterHelper(Document hashKey, IEnumerable <QueryCondition> conditions, ItemStorageConfig storageConfig, out List <string> indexNames)
        {
            if (hashKey == null)
            {
                throw new ArgumentNullException("hashKey");
            }

            if (storageConfig.HashKeyPropertyNames.Count != 1)
            {
                throw new InvalidOperationException("Must have one hash key defined for the table " + storageConfig.TableName);
            }
            if (storageConfig.RangeKeyPropertyNames.Count != 1)
            {
                throw new InvalidOperationException("Must have one range key defined for the table " + storageConfig.TableName);
            }

            QueryFilter filter = new QueryFilter();

            foreach (string hashKeyProperty in storageConfig.HashKeyPropertyNames)
            {
                PropertyStorage propertyStorage = storageConfig.GetPropertyStorage(hashKeyProperty);
                string          attributeName   = propertyStorage.AttributeName;
                DynamoDBEntry   hashValue       = hashKey[attributeName];
                filter.AddCondition(attributeName, QueryOperator.Equal, hashValue);
            }

            indexNames = new List <string>();
            if (conditions != null)
            {
                foreach (QueryCondition condition in conditions)
                {
                    object[]        conditionValues = condition.Values;
                    PropertyStorage propertyStorage = storageConfig.GetPropertyStorage(condition.PropertyName);
                    if (propertyStorage.IsLSIRangeKey)
                    {
                        indexNames.AddRange(propertyStorage.Indexes);
                    }
                    List <AttributeValue> attributeValues = new List <AttributeValue>();
                    foreach (var conditionValue in conditionValues)
                    {
                        DynamoDBEntry  entry          = ToDynamoDBEntry(propertyStorage, conditionValue);
                        AttributeValue attributeValue = entry.ConvertToAttributeValue();
                        attributeValues.Add(attributeValue);
                    }
                    filter.AddCondition(propertyStorage.AttributeName, condition.Operator, attributeValues);
                }
            }
            return(filter);
        }
Ejemplo n.º 16
0
        private static List <QueryCondition> CreateQueryConditions(DynamoDBFlatConfig flatConfig, QueryOperator op, IEnumerable <object> values, ItemStorageConfig storageConfig)
        {
            string rangeKeyPropertyName;

            string indexName = flatConfig.IndexName;

            if (string.IsNullOrEmpty(indexName))
            {
                rangeKeyPropertyName = storageConfig.RangeKeyPropertyNames.FirstOrDefault();
            }
            else
            {
                rangeKeyPropertyName = storageConfig.GetRangeKeyByIndex(indexName);
            }

            List <QueryCondition> conditions = new List <QueryCondition>
            {
                new QueryCondition(rangeKeyPropertyName, op, values.ToArray())
            };

            return(conditions);
        }
        private List <QueryCondition> CreateQueryConditions(DynamoDBOperationConfig config, QueryOperator op, IEnumerable <object> values, ItemStorageConfig storageConfig)
        {
            string rangeKeyPropertyName;

            var    flatConfig = new DynamoDBFlatConfig(config, this.config);
            string indexName  = flatConfig.IndexName;

            if (string.IsNullOrEmpty(indexName))
            {
                rangeKeyPropertyName = storageConfig.RangeKeyPropertyNames.FirstOrDefault();
            }
            else
            {
                List <string> rangeProperties;
                if (!storageConfig.IndexNameToRangePropertiesMapping.TryGetValue(indexName, out rangeProperties))
                {
                    rangeProperties = null;
                }

                if (rangeProperties == null || rangeProperties.Count != 1)
                {
                    throw new InvalidOperationException("Unable to determine range key from index name");
                }
                rangeKeyPropertyName = rangeProperties[0];
            }
            List <QueryCondition> conditions = new List <QueryCondition>
            {
                new QueryCondition(rangeKeyPropertyName, op, values.ToArray())
            };

            return(conditions);
        }
Ejemplo n.º 18
0
        private ContextSearch ConvertQueryHelper <T>(DynamoDBFlatConfig currentConfig, ItemStorageConfig storageConfig, QueryFilter filter, List <string> indexNames)
        {
            Table  table       = GetTargetTable(storageConfig, currentConfig);
            string indexName   = GetQueryIndexName(currentConfig, indexNames);
            var    queryConfig = new QueryOperationConfig
            {
                Filter              = filter,
                ConsistentRead      = currentConfig.ConsistentRead.Value,
                BackwardSearch      = currentConfig.BackwardQuery.Value,
                IndexName           = indexName,
                ConditionalOperator = currentConfig.ConditionalOperator
            };

            if (string.IsNullOrEmpty(indexName))
            {
                queryConfig.Select = SelectValues.SpecificAttributes;
                List <string> attributesToGet = storageConfig.AttributesToGet;
                queryConfig.AttributesToGet = attributesToGet;
            }
            else
            {
                queryConfig.Select = SelectValues.AllProjectedAttributes;
            }
            Search query = table.Query(queryConfig);

            return(new ContextSearch(query, currentConfig));
        }
        // Key creation
        private static DynamoDBEntry ValueToDynamoDBEntry(string propertyName, object value, ItemStorageConfig storageConfig)
        {
            PropertyStorage propertyStorage = storageConfig.GetPropertyStorage(propertyName);
            var             entry           = ToDynamoDBEntry(propertyStorage, value);

            return(entry);
        }
Ejemplo n.º 20
0
        private QueryFilter ComposeQueryFilter(DynamoDBFlatConfig currentConfig, object hashKeyValue, IEnumerable <QueryCondition> conditions, ItemStorageConfig storageConfig, out List <string> indexNames)
        {
            if (hashKeyValue == null)
            {
                throw new ArgumentNullException("hashKeyValue");
            }

            // Set hash key property name
            // In case of index queries, if GSI, different key could be used
            string hashKeyProperty = storageConfig.HashKeyPropertyNames[0];

            hashKeyProperty = storageConfig.GetCorrectHashKeyProperty(currentConfig, hashKeyProperty);

            PropertyStorage propertyStorage   = storageConfig.GetPropertyStorage(hashKeyProperty);
            string          hashAttributeName = propertyStorage.AttributeName;

            DynamoDBEntry hashKeyEntry = ValueToDynamoDBEntry(propertyStorage, hashKeyValue, currentConfig);

            if (hashKeyEntry == null)
            {
                throw new InvalidOperationException("Unable to convert hash key value for property " + hashKeyProperty);
            }

            Document hashKey = new Document();

            hashKey[hashAttributeName] = hashKeyEntry;

            return(ComposeQueryFilterHelper(currentConfig, hashKey, conditions, storageConfig, out indexNames));
        }
Ejemplo n.º 21
0
        internal static ItemStorageConfig CreateStorageConfig(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            ItemStorageConfig config = new ItemStorageConfig(type);

            DynamoDBTableAttribute tableAttribute = Utils.GetTableAttribute(type);

            if (tableAttribute == null || string.IsNullOrEmpty(tableAttribute.TableName))
            {
                throw new InvalidOperationException("No DynamoDBTableAttribute on type");
            }

            if (string.IsNullOrEmpty(tableAttribute.TableName))
            {
                throw new InvalidOperationException("DynamoDBTableAttribute.Table is empty or null");
            }
            config.TableName = tableAttribute.TableName;
            config.LowerCamelCaseProperties = tableAttribute.LowerCamelCaseProperties;

            foreach (var member in type.GetMembers())
            {
                // filter out non-fields and non-properties
                if (!(member is FieldInfo || member is PropertyInfo))
                {
                    continue;
                }

                // filter out properties that aren't both read and write
                if (!Utils.IsReadWrite(member))
                {
                    continue;
                }

                DynamoDBAttribute attribute = Utils.GetAttribute(member);

                // filter out ignored properties
                if (attribute is DynamoDBIgnoreAttribute)
                {
                    continue;
                }

                Type   memberType    = Utils.GetType(member);
                string attributeName = GetAccurateCase(config, member.Name);
                string propertyName  = member.Name;

                PropertyStorage propertyStorage = new PropertyStorage
                {
                    Member     = member,
                    MemberType = memberType,
                };

                if (attribute is DynamoDBVersionAttribute)
                {
                    Utils.ValidateVersionType(memberType);    // no conversion is possible, so type must be a nullable primitive

                    propertyStorage.IsVersion = true;
                }

                DynamoDBPropertyAttribute propertyAttribute = attribute as DynamoDBPropertyAttribute;
                if (propertyAttribute != null)
                {
                    if (!string.IsNullOrEmpty(propertyAttribute.AttributeName))
                    {
                        attributeName = GetAccurateCase(config, propertyAttribute.AttributeName);
                    }

                    if (propertyAttribute is DynamoDBHashKeyAttribute)
                    {
                        if (propertyAttribute.Converter == null && !Utils.IsPrimitive(memberType))
                        {
                            throw new InvalidOperationException("Hash key " + propertyName + " must be of primitive type");
                        }

                        propertyStorage.IsHashKey = true;
                    }
                    if (propertyAttribute is DynamoDBRangeKeyAttribute)
                    {
                        if (propertyAttribute.Converter == null && !Utils.IsPrimitive(memberType))
                        {
                            throw new InvalidOperationException("Range key " + propertyName + " must be of primitive type");
                        }

                        propertyStorage.IsRangeKey = true;
                    }
                    if (propertyAttribute is DynamoDBLocalSecondaryIndexRangeKeyAttribute)
                    {
                        DynamoDBLocalSecondaryIndexRangeKeyAttribute lsiRangeKeyAttribute = propertyAttribute as DynamoDBLocalSecondaryIndexRangeKeyAttribute;
                        if (lsiRangeKeyAttribute.IndexNames == null || lsiRangeKeyAttribute.IndexNames.Length == 0)
                        {
                            throw new InvalidOperationException("Local Secondary Index must not be null or empty");
                        }
                        propertyStorage.Indexes.AddRange(lsiRangeKeyAttribute.IndexNames);
                    }

                    if (propertyAttribute.Converter != null)
                    {
                        if (!Utils.CanInstantiate(propertyAttribute.Converter) || !Utils.ImplementsInterface(propertyAttribute.Converter, typeof(IPropertyConverter)))
                        {
                            throw new InvalidOperationException("Converter for " + propertyName + " must be instantiable with no parameters and must implement IPropertyConverter");
                        }

                        propertyStorage.Converter = Utils.Instantiate(propertyAttribute.Converter) as IPropertyConverter;
                    }
                }

                propertyStorage.PropertyName  = propertyName;
                propertyStorage.AttributeName = attributeName;

                config.AddPropertyStorage(propertyStorage);
            }

            if (config.HashKeyPropertyNames.Count == 0)
            {
                throw new InvalidOperationException("No hash key configured for type " + type.FullName);
            }

            return(config);
        }