Пример #1
0
 public override void VisitResultOperator(Remotion.Linq.Clauses.ResultOperatorBase resultOperator, QueryModel queryModel, int index)
 {
     if (index > 0)
     {
         _isInstanceQuery = false;
     }
     if (resultOperator is TakeResultOperator)
     {
         var take = resultOperator as TakeResultOperator;
         _queryBuilder.Limit = take.GetConstantCount();
         if (_queryBuilder.Limit != 1)
         {
             _isInstanceQuery = false;
         }
         return;
     }
     if (resultOperator is SkipResultOperator)
     {
         var skip = resultOperator as SkipResultOperator;
         _queryBuilder.Offset = skip.GetConstantCount();
         return;
     }
     if (resultOperator is AverageResultOperator && index == 0)
     {
         var varName = GetExpressionVariable(queryModel.SelectClause.Selector);
         if (varName != null)
         {
             _queryBuilder.ApplyAggregate("AVG", varName);
             return;
         }
     }
     if (resultOperator is SumResultOperator && index == 0)
     {
         var varName = GetExpressionVariable(queryModel.SelectClause.Selector);
         if (varName != null)
         {
             _queryBuilder.ApplyAggregate("SUM", varName);
             return;
         }
     }
     if (resultOperator is CountResultOperator && index == 0)
     {
         var varName = GetExpressionVariable(queryModel.SelectClause.Selector);
         if (varName != null)
         {
             _queryBuilder.ApplyAggregate("COUNT", varName);
             return;
         }
     }
     if (resultOperator is LongCountResultOperator && index == 0)
     {
         var varName = GetExpressionVariable(queryModel.SelectClause.Selector);
         if (varName != null)
         {
             _queryBuilder.ApplyAggregate("COUNT", varName);
             return;
         }
     }
     if (resultOperator is MinResultOperator && index == 0)
     {
         var varName = GetExpressionVariable(queryModel.SelectClause.Selector);
         if (varName != null)
         {
             _queryBuilder.ApplyAggregate("MIN", varName);
             return;
         }
     }
     if (resultOperator is MaxResultOperator && index == 0)
     {
         var varName = GetExpressionVariable(queryModel.SelectClause.Selector);
         if (varName != null)
         {
             _queryBuilder.ApplyAggregate("MAX", varName);
             return;
         }
     }
     if (resultOperator is SingleResultOperator && index == 0)
     {
         // Grab first 2 rows. If there are two then the outer wrapper will fail.
         _queryBuilder.Limit = 2;
         return;
     }
     if (resultOperator is FirstResultOperator)
     {
         _queryBuilder.Limit = 1;
         return;
     }
     if (resultOperator is OfTypeResultOperator)
     {
         var ofType  = resultOperator as OfTypeResultOperator;
         var varName = GetExpressionVariable(queryModel.SelectClause.Selector);
         if (varName != null)
         {
             var typeUri = _queryBuilder.Context.MapTypeToUri(ofType.SearchedItemType);
             if (typeUri != null)
             {
                 _queryBuilder.AddTripleConstraint(
                     GraphNode.Variable, varName,
                     GraphNode.Raw, "a",
                     GraphNode.Iri, typeUri);
                 return;
             }
             throw new EntityFrameworkException("No URI mapping found for type '{0}'",
                                                ofType.SearchedItemType);
         }
     }
     if (resultOperator is DistinctResultOperator)
     {
         _queryBuilder.IsDistinct = true;
         return;
     }
     if (resultOperator is GroupResultOperator)
     {
         var groupOperator = resultOperator as GroupResultOperator;
         var keyExpr       = groupOperator.KeySelector;
         var exprVar       = GetExpressionVariable(keyExpr);
         if (exprVar == null)
         {
             throw new EntityFrameworkException("Unable to convert GroupBy '{0}' operator to SPARQL.",
                                                groupOperator);
         }
         _queryBuilder.AddGroupByExpression("?" + exprVar);
         return;
     }
     if (resultOperator is CastResultOperator)
     {
         var castOperator = resultOperator as CastResultOperator;
         var mappedUri    = _queryBuilder.Context.MapTypeToUri(castOperator.CastItemType);
         if (mappedUri == null)
         {
             throw new EntityFrameworkException("Unable to cast to type '{0}' as it is not a valid entity type.", castOperator.CastItemType);
         }
         return;
     }
     if (index > 0)
     {
         throw new NotSupportedException(
                   String.Format(
                       "LINQ-to-SPARQL does not currently support the result operator '{0}' as a second or subsequent result operator.",
                       resultOperator));
     }
     throw new NotSupportedException(
               String.Format("LINQ-to-SPARQL does not currently support the result operator '{0}'", resultOperator));
 }
        protected override Expression VisitMemberExpression(MemberExpression expression)
        {
            string sourceVarName = null;

            if (expression.Expression is QuerySourceReferenceExpression)
            {
                var        source = expression.Expression as QuerySourceReferenceExpression;
                Expression mappedSourceExpression;
                sourceVarName = source.ReferencedQuerySource.ItemName;
                if (_queryBuilder.TryGetQuerySourceMapping(source.ReferencedQuerySource, out mappedSourceExpression) && mappedSourceExpression is SelectVariableNameExpression)
                {
                    sourceVarName = (mappedSourceExpression as SelectVariableNameExpression).Name;
                }
            }
            else if (expression.Expression is MemberExpression)
            {
                var memberExpression = VisitExpression(expression.Expression);
                if (memberExpression is SelectVariableNameExpression)
                {
                    sourceVarName = (memberExpression as SelectVariableNameExpression).Name;
                }
            }
            else if (expression.Expression is UnaryExpression)
            {
                var unary = expression.Expression as UnaryExpression;
                if (unary.NodeType == ExpressionType.TypeAs &&
                    unary.Operand is QuerySourceReferenceExpression)
                {
                    var targetType = unary.Type;
                    var source     = unary.Operand as QuerySourceReferenceExpression;
                    if (source != null)
                    {
                        var itemType = source.ReferencedQuerySource.ItemType;
                        if (targetType.IsAssignableFrom(itemType))
                        {
                            expression = Expression.MakeMemberAccess(unary.Operand, expression.Member);
                            return(VisitExpression(expression));
                        }
                    }
                }
                var updatedExpression = VisitExpression(expression.Expression) as UnaryExpression;
                if (updatedExpression != null && updatedExpression.Operand is SelectVariableNameExpression)
                {
#if WINDOWS_PHONE || PORTABLE
                    return(Expression.MakeMemberAccess(updatedExpression, expression.Member));
#else
                    return(expression.Update(updatedExpression));
#endif
                }
            }
            if (!String.IsNullOrEmpty(sourceVarName))
            {
#if PORTABLE
                if (expression.Member is PropertyInfo)
#else
                if (expression.Member.MemberType == MemberTypes.Property)
#endif
                {
                    var propertyInfo = expression.Member as PropertyInfo;
                    var propertyHint = _queryBuilder.Context.GetPropertyHint(propertyInfo);
                    if (propertyHint != null)
                    {
                        switch (propertyHint.MappingType)
                        {
                        case PropertyMappingType.Arc:
                        {
                            var memberVarName = _queryBuilder.GetVariableForObject(
                                GraphNode.Variable, sourceVarName,
                                GraphNode.Iri, propertyHint.SchemaTypeUri);
                            if (memberVarName == null)
                            {
                                memberVarName = _queryBuilder.NextVariable();
                                _queryBuilder.AddTripleConstraint(
                                    GraphNode.Variable, sourceVarName,
                                    GraphNode.Iri, propertyHint.SchemaTypeUri,
                                    GraphNode.Variable, memberVarName);
                            }
                            return(new SelectVariableNameExpression(memberVarName, VariableBindingType.Resource, propertyInfo.PropertyType));
                        }

                        case PropertyMappingType.InverseArc:
                        {
                            var memberVarName = _queryBuilder.GetVariableForSubject(
                                GraphNode.Iri, propertyHint.SchemaTypeUri,
                                GraphNode.Variable, sourceVarName);
                            if (memberVarName == null)
                            {
                                memberVarName = _queryBuilder.NextVariable();
                                _queryBuilder.AddTripleConstraint(
                                    GraphNode.Variable, memberVarName,
                                    GraphNode.Iri, propertyHint.SchemaTypeUri,
                                    GraphNode.Variable, sourceVarName);
                            }
                            return(new SelectVariableNameExpression(memberVarName, VariableBindingType.Resource, propertyInfo.PropertyType));
                        }

                        case PropertyMappingType.Property:
                        {
                            var propertyValueVarName = _queryBuilder.GetVariableForObject(GraphNode.Variable,
                                                                                          sourceVarName,
                                                                                          GraphNode.Iri,
                                                                                          propertyHint.
                                                                                          SchemaTypeUri);
                            if (propertyValueVarName == null)
                            {
                                propertyValueVarName = _queryBuilder.NextVariable();
                                _queryBuilder.AddTripleConstraint(
                                    GraphNode.Variable, sourceVarName,
                                    GraphNode.Iri, propertyHint.SchemaTypeUri,
                                    GraphNode.Variable, propertyValueVarName);
                            }
                            return(new SelectVariableNameExpression(propertyValueVarName,
                                                                    VariableBindingType.Literal, propertyInfo.PropertyType));
                        }

                        case PropertyMappingType.Address:
                        {
                            return(new SelectVariableNameExpression(sourceVarName, VariableBindingType.Resource, propertyInfo.PropertyType));
                        }

                        case PropertyMappingType.Id:
                        {
                            var prefix = EntityMappingStore.GetIdentifierPrefix(propertyInfo.DeclaringType);
                            return(new SelectIdentifierVariableNameExpression(sourceVarName, prefix));
                            //return new SelectVariableNameExpression(sourceVarName, VariableBindingType.Resource, propertyInfo.PropertyType);
                        }
                        }
                    }
                }
            }
            return(base.VisitMemberExpression(expression));
        }