public QueryExpression <T> QueryIndex <T>(DynamoGlobalIndex index, Expression <Func <T, bool> > keyExpression) { var q = new QueryExpression <T>(this) { IndexName = index.Name, Limit = PagingLimit, ConsistentRead = false, ScanIndexForward = this.ScanIndexForward, }; q.KeyCondition(keyExpression); return(q); }
private static DynamoMetadataType ToMetadataTable(Type type) { var alias = type.FirstAttribute <AliasAttribute>(); var props = GetTableProperties(type); Converters.GetHashAndRangeKeyFields(type, props, out var hash, out var range); var provision = type.FirstAttribute <ProvisionedThroughputAttribute>(); // If its a generic type, the type name will contain illegal characters (not accepted as DynamoDB table name) // so, remove the Tilde and make the type name unique to the runtime type of the generic string genericTypeNameAlias = null; if (type.IsGenericType) { var indexOfTilde = type.Name.IndexOf("`", StringComparison.Ordinal); indexOfTilde = indexOfTilde < 1 ? type.Name.Length - 1 : indexOfTilde; genericTypeNameAlias = type.Name.Substring(0, indexOfTilde) + type.GetGenericArguments().Select(t => t.Name).Join(); } var metadata = new DynamoMetadataType { Type = type, IsTable = true, Name = alias != null ? alias.Name : genericTypeNameAlias ?? type.Name, ReadCapacityUnits = provision?.ReadCapacityUnits, WriteCapacityUnits = provision?.WriteCapacityUnits, }; metadata.Fields = props.Map(p => new DynamoMetadataField { Parent = metadata, Type = p.PropertyType, Name = Converters.GetFieldName(p), DbType = Converters.GetFieldType(p.PropertyType), IsHashKey = p == hash, IsRangeKey = p == range, ExcludeNullValue = p.HasAttribute <IndexAttribute>() || p.HasAttribute <ExcludeNullValueAttribute>(), IsAutoIncrement = p.HasAttribute <AutoIncrementAttribute>(), SetValueFn = p.CreateSetter(), GetValueFn = p.CreateGetter(), }).ToArray(); metadata.HashKey = metadata.Fields.FirstOrDefault(x => x.IsHashKey); metadata.RangeKey = metadata.Fields.FirstOrDefault(x => x.IsRangeKey); if (metadata.HashKey == null) { throw new ArgumentException($"Could not infer Hash Key in Table '{type.Name}'"); } var hashField = metadata.HashKey.Name; string indexName = null; metadata.LocalIndexes = props.Where(x => x.HasAttribute <IndexAttribute>()).Map(x => { var indexProjection = x.FirstAttribute <ProjectionTypeAttribute>(); var projectionType = indexProjection?.ProjectionType ?? DynamoProjectionType.Include; indexName = metadata.Name.ToIndexName(IndexType.Local, x.Name, metadata.HashKey.Name); return(new DynamoLocalIndex { Name = indexName, HashKey = metadata.HashKey, RangeKey = metadata.GetField(x.Name), ProjectionType = DynamoProjectionType.All, ProjectedFields = new string[] { "" } }); }); metadata.GlobalIndexes = props.Where(x => x.HasAttribute <GlobalSecondaryIndexHashKeyAttribute>()).Map(x => { var indexProjection = x.FirstAttribute <ProjectionTypeAttribute>(); var globalSecondaryIndexHashKeyAttribute = x.GetCustomAttribute <GlobalSecondaryIndexHashKeyAttribute>(); var rangeKey = globalSecondaryIndexHashKeyAttribute.RangeKey; bool hasRangeKey = !string.IsNullOrEmpty(rangeKey); //string indexName = (hasRangeKey) ? $"{metadata.Name}-GSI-{x.Name}-{rangeKey}-Index" : $"{metadata.Name}-GSI-{x.Name}-Index"; indexName = metadata.Name.ToIndexName(IndexType.Global, x.Name, null, rangeKey); var dynamoIndex = new DynamoGlobalIndex { Name = indexName, HashKey = metadata.GetField(x.Name), RangeKey = metadata.GetField(rangeKey), ProjectionType = DynamoProjectionType.All, ProjectedFields = new string[] { "" } }; if (hasRangeKey) { dynamoIndex.RangeKey = metadata.GetField(rangeKey); } return(dynamoIndex); }); var references = type.AllAttributes <ReferencesAttribute>(); foreach (var attr in references) { var localIndex = attr.Type.GetTypeWithGenericInterfaceOf(typeof(ILocalIndex <>)); if (localIndex != null) { metadata.LocalIndexes.Add(CreateLocalIndex(type, metadata, hashField, attr.Type)); } var globalIndex = attr.Type.GetTypeWithGenericInterfaceOf(typeof(IGlobalIndex <>)); if (globalIndex != null) { metadata.GlobalIndexes.Add(CreateGlobalIndex(type, metadata, attr.Type)); } } return(metadata); }