예제 #1
0
        private void ProcessRoot(KeyLookupQueryNode keyLookup)
        {
            var keyPropertyValues = keyLookup.KeyPropertyValues.ToList();

            if (keyPropertyValues.Count == 1)
            {
                var kpv        = keyPropertyValues[0];
                var rootEntity = kpv.KeyProperty.DeclaringType as IEdmEntityType; // Get the entity that declares the Id property
                if (rootEntity != null)
                {
                    string prefix;
                    if (_map.TryGetIdentifierPrefixForProperty(rootEntity.FullName(), kpv.KeyProperty.Name, out prefix))
                    {
                        object keyValue = ProcessNode(kpv.KeyValue);
                        if (keyValue != null)
                        {
                            _sparqlModel.SelectEntity(
                                prefix + keyValue, keyLookup.Collection.ItemType.FullName());
                        }
                    }
                }
            }
        }
예제 #2
0
        private object ProcessKeyLookup(KeyLookupQueryNode keyLookup)
        {
            var keyPropertyValues = keyLookup.KeyPropertyValues.ToList();

            if (keyPropertyValues.Count == 1)
            {
                var kpv        = keyPropertyValues[0];
                var rootEntity = kpv.KeyProperty.DeclaringType as IEdmEntityType; // Get the entity that declares the Id property
                if (rootEntity != null)
                {
                    string prefix;
                    if (_map.TryGetIdentifierPrefixForProperty(rootEntity.FullName(), kpv.KeyProperty.Name, out prefix))
                    {
                        object keyValue = ProcessNode(kpv.KeyValue);
                        if (keyValue != null)
                        {
                            return(new Uri(prefix + keyValue));
                        }
                    }
                }
            }
            throw new Exception("Could not process key lookup");
        }
        protected virtual Expression TranslateKeyLookup(KeyLookupQueryNode keyLookupNode)
        {
            ExceptionUtils.CheckArgumentNotNull(keyLookupNode, "keyLookupNode");
            ExceptionUtils.CheckArgumentNotNull(keyLookupNode.Collection, "keyLookupNode.Collection");
            ExceptionUtils.CheckArgumentNotNull(keyLookupNode.Collection.ItemType, "keyLookupNode.Collection.ItemType");
            ExceptionUtils.CheckArgumentNotNull(keyLookupNode.KeyPropertyValues, "keyLookupNode.KeyPropertyValues");

            IEdmTypeReference itemType = keyLookupNode.Collection.ItemType;
            if (keyLookupNode.Collection.ItemType.TypeKind() != EdmTypeKind.Entity)
            {
                throw new ODataException(Strings.QueryExpressionTranslator_KeyLookupOnlyOnEntities(keyLookupNode.Collection.ItemType.ODataFullName(), keyLookupNode.Collection.ItemType.TypeKind()));
            }

            IEdmEntityTypeReference itemEntityType = itemType.AsEntityOrNull();
            Debug.Assert(itemEntityType != null, "itemEntityType != null");

            Expression collectionExpression = this.Translate(keyLookupNode.Collection);
            Type expectedCollectionExpressionType = typeof(IQueryable<>).MakeGenericType(itemType.GetInstanceType(this.model));
            if (!expectedCollectionExpressionType.IsAssignableFrom(collectionExpression.Type))
            {
                throw new ODataException(Strings.QueryExpressionTranslator_KeyLookupOnlyOnQueryable(collectionExpression.Type, expectedCollectionExpressionType));
            }

            ParameterExpression parameter = Expression.Parameter(itemType.GetInstanceType(this.model), "it");
            Expression body = null;

            // We have to walk the key properties as declared on the type to get the declared order (rather than the order in the query)
            // So we need to cache the key properties in a list so that we can look them up. This is necessary to avoid enumerating the IEnumerable
            // specified on the Key lookup node multiple times (since we don't know how costly it is and if it's actually possible).
            List<KeyPropertyValue> keyPropertyValuesCache = new List<KeyPropertyValue>(keyLookupNode.KeyPropertyValues);
            foreach (IEdmStructuralProperty keyProperty in itemEntityType.Key())
            {
                // Find the value for the key property and verify that it's specified exactly once.
                KeyPropertyValue keyPropertyValue = null;
                foreach (KeyPropertyValue candidateKeyPropertyValue in keyPropertyValuesCache.Where(kpv => kpv.KeyProperty == keyProperty))
                {
                    if (keyPropertyValue != null)
                    {
                        throw new ODataException(Strings.QueryExpressionTranslator_KeyLookupWithoutKeyProperty(keyProperty.Name, itemType.ODataFullName()));
                    }

                    keyPropertyValue = candidateKeyPropertyValue;
                }

                if (keyPropertyValue == null)
                {
                    throw new ODataException(Strings.QueryExpressionTranslator_KeyLookupWithoutKeyProperty(keyProperty.Name, itemType.ODataFullName()));
                }

                // NOTE: using Any() instead of Contains() since Contains() does not exist on all platforms
                if (keyPropertyValue.KeyProperty == null || !itemEntityType.Key().Any(k => k == keyPropertyValue.KeyProperty))
                {
                    throw new ODataException(Strings.QueryExpressionTranslator_KeyPropertyValueWithoutProperty);
                }

                if (keyPropertyValue.KeyValue == null || 
                    keyPropertyValue.KeyValue.TypeReference == null || 
                    !keyPropertyValue.KeyValue.TypeReference.IsEquivalentTo(keyPropertyValue.KeyProperty.Type))
                {
                    throw new ODataException(Strings.QueryExpressionTranslator_KeyPropertyValueWithWrongValue(keyPropertyValue.KeyProperty.Name));
                }

                Expression keyPropertyAccess = this.CreatePropertyAccessExpression(parameter, itemEntityType, keyPropertyValue.KeyProperty);

                Expression keyValueExpression = this.Translate(keyPropertyValue.KeyValue);
#if DEBUG
                Debug.Assert(
                    TypeUtils.AreTypesEquivalent(keyPropertyAccess.Type, keyValueExpression.Type), 
                    "The types of the expression should have been checked against the metadata types which are equal.");
#endif

                Expression keyPredicate = Expression.Equal(
                    keyPropertyAccess,
                    keyValueExpression);

                if (body == null)
                {
                    body = keyPredicate;
                }
                else
                {
                    body = Expression.AndAlso(body, keyPredicate);
                }
            }

            if (body == null)
            {
                throw new ODataException(Strings.QueryExpressionTranslator_KeyLookupWithNoKeyValues);
            }

            return Expression.Call(
                typeof(Queryable),
                WhereMethodName,
                new Type[] { itemType.GetInstanceType(this.model) },
                collectionExpression,
                Expression.Quote(Expression.Lambda(body, parameter)));
        }
예제 #4
0
 private void ProcessRoot(KeyLookupQueryNode keyLookup)
 {
     var keyPropertyValues = keyLookup.KeyPropertyValues.ToList();
     if (keyPropertyValues.Count == 1)
     {
         var kpv = keyPropertyValues[0];
         var rootEntity = kpv.KeyProperty.DeclaringType as IEdmEntityType; // Get the entity that declares the Id property
         if (rootEntity != null)
         {
             string prefix;
             if (_map.TryGetIdentifierPrefixForProperty(rootEntity.FullName(), kpv.KeyProperty.Name, out prefix))
             {
                 object keyValue = ProcessNode(kpv.KeyValue);
                 if (keyValue != null)
                 {
                     _sparqlModel.SelectEntity(
                         prefix + keyValue, keyLookup.Collection.ItemType.FullName());
                 }
             }
         }
     }
 }
예제 #5
0
 private object ProcessKeyLookup(KeyLookupQueryNode keyLookup)
 {
     var keyPropertyValues = keyLookup.KeyPropertyValues.ToList();
     if (keyPropertyValues.Count == 1)
     {
         var kpv = keyPropertyValues[0];
         var rootEntity = kpv.KeyProperty.DeclaringType as IEdmEntityType; // Get the entity that declares the Id property
         if (rootEntity != null)
         {
             string prefix;
             if (_map.TryGetIdentifierPrefixForProperty(rootEntity.FullName(), kpv.KeyProperty.Name, out prefix))
             {
                 object keyValue = ProcessNode(kpv.KeyValue);
                 if (keyValue != null)
                 {
                     return new Uri(prefix + keyValue);
                 }
             }
         }
     }
     throw new Exception("Could not process key lookup");
 }