示例#1
0
            /// <inheritdoc/>
            public Expression Expand(QueryExpressionContext context)
            {
                Ensure.NotNull(context, "context");

                var result = CallInner(context);

                if (result != null)
                {
                    return(result);
                }

                // Ensure this query constructs from DataSourceStub.
                if (context.ModelReference is DataSourceStubModelReference)
                {
                    // Only expand entity set query which returns IQueryable<T>.
                    var query = ModelCache.GetEntitySetQuery(context);
                    if (query != null)
                    {
                        return(query.Expression);
                    }
                }

                // No expansion happened just return the node itself.
                return(context.VisitedNode);
            }
示例#2
0
        /// <inheritdoc/>
        public Expression Expand(QueryExpressionContext context)
        {
            IQueryable result = GetEntitySetQuery(context);

            if (result != null)
            {
                // Only Expand to expression of method call on ApiData class
                var methodCall = result.Expression as MethodCallExpression;
                if (methodCall != null)
                {
                    var method = methodCall.Method;
                    if (method.DeclaringType == typeof(ApiData) && method.Name != "Value")
                    {
                        return(null);
                    }
                    else
                    {
                        return(result.Expression);
                    }
                }

                return(null);
            }

            return(null);
        }
示例#3
0
        /// <inheritdoc/>
        public Expression Filter(QueryExpressionContext context)
        {
            Ensure.NotNull(context, "context");
            if (context.ModelReference == null)
            {
                return(null);
            }

            var apiDataReference = context.ModelReference as ApiDataReference;

            if (apiDataReference == null)
            {
                return(null);
            }

            var entitySet = apiDataReference.Element as IEdmEntitySet;

            if (entitySet == null)
            {
                return(null);
            }

            var returnType = context.VisitedNode.Type
                             .FindGenericType(typeof(IQueryable <>));
            var elementType = returnType.GetGenericArguments()[0];
            var methodName  = ConventionBasedChangeSetConstants.FilterMethodEntitySetFilter + entitySet.Name;
            var method      = this.targetType.GetQualifiedMethod(methodName);

            if (method != null && method.IsFamily &&
                method.ReturnType == returnType)
            {
                object target = null;
                if (!method.IsStatic)
                {
                    target = context.QueryContext.ApiContext.GetProperty(
                        typeof(Api).AssemblyQualifiedName);
                    if (target == null ||
                        !this.targetType.IsAssignableFrom(target.GetType()))
                    {
                        return(null);
                    }
                }

                var parameters = method.GetParameters();
                if (parameters.Length == 1 &&
                    parameters[0].ParameterType == returnType)
                {
                    var queryType = typeof(EnumerableQuery <>)
                                    .MakeGenericType(elementType);
                    var query  = Activator.CreateInstance(queryType, context.VisitedNode);
                    var result = method.Invoke(target, new object[] { query }) as IQueryable;
                    if (result != null && result != query)
                    {
                        return(result.Expression);
                    }
                }
            }

            return(null);
        }
示例#4
0
        /// <inheritdoc/>
        public Expression Filter(QueryExpressionContext context)
        {
            Ensure.NotNull(context, "context");

            if (Inner != null)
            {
                var innerFilteredExpression = Inner.Filter(context);
                if (innerFilteredExpression != null && innerFilteredExpression != context.VisitedNode)
                {
                    return(innerFilteredExpression);
                }
            }

            // TODO GitHubIssue#330: EF QueryExecutor will throw exception if check whether collections is null added.
            // Error message likes "Cannot compare elements of type 'ICollection`1[[EntityType]]'.
            // Only primitive types, enumeration types and entity types are supported."
            if (context.VisitedNode.NodeType == ExpressionType.NotEqual)
            {
                var  binaryExp = (BinaryExpression)context.VisitedNode;
                var  left      = binaryExp.Left as MemberExpression;
                var  right     = binaryExp.Right as ConstantExpression;
                bool leftCheck = left != null && left.Type.IsGenericType &&
                                 left.Type.GetGenericTypeDefinition() == typeof(ICollection <>);
                bool rightCheck = right != null && right.Value == null;
                if (leftCheck && rightCheck)
                {
                    return(Expression.Constant(true));
                }
            }

            return(context.VisitedNode);
        }
        /// <summary>
        /// Expands an expression.
        /// </summary>
        /// <param name="context">
        /// The query expression context.
        /// </param>
        /// <returns>
        /// An expanded expression of the same type as the visited node, or
        /// if expansion did not apply, the visited node or <c>null</c>.
        /// </returns>
        public Expression Expand(QueryExpressionContext context)
        {
            Ensure.NotNull(context, "context");

            if (this.InnerHandler != null)
            {
                var result = this.InnerHandler.Expand(context);
                if (result != null)
                {
                    return(result);
                }
            }

            if (context.ModelReference == null)
            {
                return(null);
            }

            var apiDataReference = context.ModelReference as ApiDataReference;

            if (apiDataReference == null)
            {
                return(null);
            }

            var entitySet = apiDataReference.Element as IEdmEntitySet;

            if (entitySet == null)
            {
                return(null);
            }

            var target = context.QueryContext.ApiContext.GetProperty(
                typeof(Api).AssemblyQualifiedName);
            var entitySetProperty = target.GetType().GetProperties(
                BindingFlags.Public | BindingFlags.Instance |
                BindingFlags.Static | BindingFlags.DeclaredOnly)
                                    .SingleOrDefault(p => p.Name == entitySet.Name);

            if (entitySetProperty != null)
            {
                var policies = entitySetProperty.GetCustomAttributes()
                               .OfType <IApiPolicy>();

                foreach (var policy in policies)
                {
                    policy.Activate(context.QueryContext);
                }

                context.AfterNestedVisitCallback = () =>
                {
                    foreach (var policy in policies.Reverse())
                    {
                        policy.Deactivate(context.QueryContext);
                    }
                };
            }

            return(context.VisitedNode);
        }
        /// <summary>	Sources an expression. </summary>
        ///
        /// <param name="context">  The query expression context. </param>
        /// <param name="embedded">	Indicates if the sourcing is occurring on an embedded node. </param>
        ///
        /// <returns>	A data source expression that represents the visited node. </returns>
        public System.Linq.Expressions.Expression Source(QueryExpressionContext context, bool embedded)
        {
            //Source query expression dynamically
            var dbContext = context.QueryContext.ApiContext.GetProperty <DynamicContext>(DynamicContext.cDbContextKey);

            if (dbContext != null)
            {
                string name = context.ModelReference.EntitySet.Name;
                Type   type = dbContext.GetModelType(name);
                if (type != null)
                {
                    var dbSet = dbContext.Set(type);
                    return(Expression.Constant(dbSet));
                }
            }

            if (this.InnerHandler != null)
            {
                return(this.InnerHandler.Source(context, embedded));
            }
            else
            {
                throw new NotImplementedException();
            }
        }
        /// <inheritdoc/>
        public Expression Process(QueryExpressionContext context)
        {
            Ensure.NotNull(context, "context");

            if (Inner != null)
            {
                var innerFilteredExpression = Inner.Process(context);
                if (innerFilteredExpression != null && innerFilteredExpression != context.VisitedNode)
                {
                    return(innerFilteredExpression);
                }
            }

            // TODO GitHubIssue#330: EF QueryExecutor will throw exception if check whether collections is null added.
            // Exception message likes "Cannot compare elements of type 'ICollection`1[[EntityType]]'.
            // Only primitive types, enumeration types and entity types are supported."
            // EF does not support complex != null neither, and it requires complex not null.
            // EF model builder set complex type not null by default, but Web Api OData does not.
            if (context.VisitedNode.NodeType == ExpressionType.NotEqual)
            {
                var binaryExp = (BinaryExpression)context.VisitedNode;
                var left      = binaryExp.Left as MemberExpression;
                var right     = binaryExp.Right as ConstantExpression;

                bool rightCheck = right != null && right.Value == null;

                // Check right first which is simple
                if (!rightCheck)
                {
                    return(context.VisitedNode);
                }

                bool leftCheck = false;
                if (left != null)
                {
                    // If it is a collection, then replace coll != null with true
                    leftCheck = left.Type.IsGenericType &&
                                left.Type.GetGenericTypeDefinition() == typeof(ICollection <>);

                    // If it is a complex, replace complex!=null with true
                    if (!leftCheck)
                    {
                        var modelRef = context.GetModelReferenceForNode(left);
                        if (modelRef != null && modelRef.Type != null)
                        {
                            leftCheck = modelRef.Type.TypeKind.Equals(EdmTypeKind.Complex);
                        }
                    }
                }

                if (leftCheck)
                {
                    return(Expression.Constant(true));
                }
            }

            return(context.VisitedNode);
        }
示例#8
0
            private Expression CallInner(QueryExpressionContext context)
            {
                if (this.InnerHandler != null)
                {
                    return(this.InnerHandler.Expand(context));
                }

                return(null);
            }
示例#9
0
            private Expression CallInner(QueryExpressionContext context, bool embedded)
            {
                if (this.InnerHandler != null)
                {
                    return(this.InnerHandler.ReplaceQueryableSource(context, embedded));
                }

                return(null);
            }
示例#10
0
        public static SelectQueryInfo VisitQueryExpression(QueryExpressionContext context)
        {
            if (context.queryExpression() != null)
            {
                return(VisitQueryExpression(context.queryExpression()));
            }

            return(VisitQuerySpecification(context.querySpecification()));
        }
示例#11
0
        public static QsiTableNode VisitQueryExpression(QueryExpressionContext context)
        {
            if (context.querySpecification() != null)
            {
                return(VisitQuerySpecification(context.querySpecification()));
            }

            return(VisitQueryExpression(context.queryExpression()));
        }
 /// <summary>	Expands an expression. </summary>
 ///
 /// <param name="context">	The query expression context. </param>
 ///
 /// <returns>
 /// An expanded expression of the same type as the visited node, or if expansion did not apply,
 /// the visited node or <c>null</c>.
 /// </returns>
 public System.Linq.Expressions.Expression Expand(QueryExpressionContext context)
 {
     //TODO: Expand query expression dynamically
     if (this.InnerHandler != null)
     {
         return(this.InnerHandler.Expand(context));
     }
     else
     {
         throw new NotImplementedException();
     }
 }
示例#13
0
        /// <summary>
        /// Expands an expression.
        /// </summary>
        /// <param name="context">
        /// The query expression context.
        /// </param>
        /// <returns>
        /// An expanded expression of the same type as the visited node, or
        /// if expansion did not apply, the visited node or <c>null</c>.
        /// </returns>
        public Expression Expand(QueryExpressionContext context)
        {
            Ensure.NotNull(context, "context");

            if (context.ModelReference == null)
            {
                return(CallInner(context));
            }

            var dataSourceStubReference = context.ModelReference as DataSourceStubReference;

            if (dataSourceStubReference == null)
            {
                return(CallInner(context));
            }

            var entitySet = dataSourceStubReference.Element as IEdmEntitySet;

            if (entitySet == null)
            {
                return(CallInner(context));
            }

            var target            = context.QueryContext.GetApiService <ApiBase>();
            var entitySetProperty = target.GetType().GetProperties(
                BindingFlags.Public | BindingFlags.Instance |
                BindingFlags.Static | BindingFlags.DeclaredOnly)
                                    .SingleOrDefault(p => p.Name == entitySet.Name);

            if (entitySetProperty != null)
            {
                var policies = entitySetProperty.GetCustomAttributes()
                               .OfType <IApiPolicy>();

                foreach (var policy in policies)
                {
                    policy.Activate(context.QueryContext);
                }

                context.AfterNestedVisitCallback = () =>
                {
                    foreach (var policy in policies.Reverse())
                    {
                        policy.Deactivate(context.QueryContext);
                    }
                };
            }

            // This class is used to activate and deactivate the policies
            // thus it is NOT intended to actually expand any query here.
            return(CallInner(context));
        }
        /// <summary>
        /// Inspects an expression.
        /// </summary>
        /// <param name="context">
        /// The query expression context.
        /// </param>
        /// <returns>
        /// <c>true</c> if the inspection passed; otherwise, <c>false</c>.
        /// </returns>
        public bool Inspect(QueryExpressionContext context)
        {
            Ensure.NotNull(context, "context");

            // TODO GitHubIssue#35 : Support Inspect more elements in authorization
            if (context.ModelReference == null)
            {
                return(true);
            }

            var apiDataReference = context.ModelReference as ApiDataReference;

            if (apiDataReference == null)
            {
                return(true);
            }

            var entitySet = apiDataReference.Element as IEdmEntitySet;

            if (entitySet == null)
            {
                return(true);
            }

            var assertedRoles = context.QueryContext
                                .GetProperty <List <string> >(AssertedRoles);
            var permissions = context.QueryContext.ApiContext.Configuration
                              .GetProperty <IEnumerable <ApiPermission> >(Permissions);

            if (permissions == null)
            {
                throw new SecurityException(
                          string.Format(CultureInfo.InvariantCulture, Resources.ReadDeniedOnEntitySet, entitySet.Name));
            }

            permissions = permissions.Where(p => (
                                                p.PermissionType == ApiPermissionType.All ||
                                                p.PermissionType == ApiPermissionType.Read) && (
                                                (p.NamespaceName == null && p.SecurableName == null) ||
                                                (p.NamespaceName == null && p.SecurableName == entitySet.Name)) &&
                                            p.ChildName == null && (p.Role == null || this.IsInRole(p.Role) ||
                                                                    (assertedRoles != null && assertedRoles.Contains(p.Role))));
            if (!permissions.Any() || permissions.Any(p => p.IsDeny))
            {
                throw new SecurityException(
                          string.Format(CultureInfo.InvariantCulture, Resources.ReadDeniedOnEntitySet, entitySet.Name));
            }

            return(true);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="QueryExpressionContextTests"/> class.
        /// </summary>
        public QueryExpressionContextTests()
        {
            serviceProviderFixture = new ServiceProviderMock();
            var api             = new TestApi(serviceProviderFixture.ServiceProvider.Object);
            var queryableSource = new QueryableSource <Test>(Expression.Constant(new Mock <IQueryable>().Object));
            var request         = new QueryRequest(queryableSource);

            queryContext = new QueryContext(api, request);
            testClass    = new QueryExpressionContext(queryContext);
            var type       = typeof(DataSourceStub);
            var methodInfo = type.GetMethods(BindingFlags.Public | BindingFlags.Static).Where(x => x.Name == "GetQueryableSource");

            testGetQuerableSource = methodInfo.First().MakeGenericMethod(new Type[] { typeof(Test) });
        }
示例#16
0
        public Expression Source(QueryExpressionContext context, bool embedded)
        {
            var orders = new[]
            {
                new Order {Id = 234}
            };

            if (!embedded)
            {
                if (context.VisitedNode.ToString().StartsWith("Source(\"Orders\""))
                {
                    return Expression.Constant(orders.AsQueryable());
                }
            }

            return context.VisitedNode;
        }
示例#17
0
        /// <summary>
        /// Sources an expression.
        /// </summary>
        /// <param name="context">
        /// The query expression context.
        /// </param>
        /// <param name="embedded">
        /// Indicates if the sourcing is occurring on an embedded node.
        /// </param>
        /// <returns>
        /// A data source expression that represents the visited node.
        /// </returns>
        public Expression ReplaceQueryableSource(QueryExpressionContext context, bool embedded)
        {
            Ensure.NotNull(context, nameof(context));

            if (context.ModelReference.EntitySet == null)
            {
                // EF provider can only source *ResourceSet*.
                return(null);
            }


            if (!(context.QueryContext.Api is IEntityFrameworkApi frameworkApi))
            {
                // Not an EF Api.
                return(null);
            }

            var dbContextType = frameworkApi.ContextType;
            var dbContext     = frameworkApi.DbContext;

            var dbSetProperty = frameworkApi.ContextType.GetProperties()
                                .FirstOrDefault(prop => prop.Name == context.ModelReference.EntitySet.Name);

            if (dbSetProperty == null)
            {
                // EF provider can only source EntitySet from *DbSet property*.
                return(null);
            }

            if (!embedded)
            {
                // TODO GitHubIssue#37 : Add API entity manager for tracking entities
                // the underlying DbContext shouldn't track the entities
                var dbSet = dbSetProperty.GetValue(dbContext);

                ////dbSet = dbSet.GetType().GetMethod("AsNoTracking").Invoke(dbSet, null);
                return(Expression.Constant(dbSet));
            }
            else
            {
                return(Expression.MakeMemberAccess(
                           Expression.Constant(dbContext),
                           dbSetProperty));
            }
        }
示例#18
0
        private IQueryable GetSingletonQuery(QueryExpressionContext context)
        {
            Ensure.NotNull(context, "context");
            if (context.ModelReference == null)
            {
                return(null);
            }

            var dataSourceStubReference = context.ModelReference as DataSourceStubModelReference;

            if (dataSourceStubReference == null)
            {
                return(null);
            }

            var singleton = dataSourceStubReference.Element as IEdmSingleton;

            if (singleton == null)
            {
                return(null);
            }

            var singletonProperty = this.singletonProperties
                                    .SingleOrDefault(p => p.Name == singleton.Name);

            if (singletonProperty != null)
            {
                object target = null;
                if (!singletonProperty.GetMethod.IsStatic)
                {
                    target = context.QueryContext.GetApiService <ApiBase>();
                    if (target == null ||
                        !this.targetType.IsInstanceOfType(target))
                    {
                        return(null);
                    }
                }

                var value = Array.CreateInstance(singletonProperty.PropertyType, 1);
                value.SetValue(singletonProperty.GetValue(target), 0);
                return(value.AsQueryable());
            }

            return(null);
        }
示例#19
0
        public CommonQueryContext(QueryExpressionContext queryExpression, LockingClauseListContext lockingClauseList)
        {
            if (queryExpression == null)
            {
                throw new ArgumentNullException(nameof(queryExpression));
            }

            WithClause             = queryExpression.withClause();
            QueryExpressionBody    = queryExpression.queryExpressionBody();
            QueryExpressionParens  = queryExpression.queryExpressionParens();
            OrderClause            = queryExpression.orderClause();
            LimitClause            = queryExpression.limitClause();
            ProcedureAnalyseClause = queryExpression.procedureAnalyseClause();
            LockingClauseList      = lockingClauseList;

            Start = queryExpression.Start;
            Stop  = lockingClauseList?.Stop ?? queryExpression.Stop;
        }
        public void InnerProcessorShortCircuits()
        {
            var api                    = new QueryFilterApi(serviceProvider);
            var instance               = new ConventionBasedQueryExpressionProcessor(typeof(EmptyApi));
            var queryable              = api.GetQueryableSource("Tests");
            var queryRequest           = new QueryRequest(queryable);
            var queryContext           = new QueryContext(api, queryRequest);
            var queryExpressionContext = new QueryExpressionContext(queryContext);
            var processorMock          = new Mock <IQueryExpressionProcessor>();
            var expression             = Expression.Constant(42);

            processorMock.Setup(x => x.Process(queryExpressionContext)).Returns(expression);
            instance.Inner = processorMock.Object;

            var result = instance.Process(queryExpressionContext);

            result.Should().Be(expression);
        }
示例#21
0
        private IQueryable GetEntitySetQuery(QueryExpressionContext context)
        {
            Ensure.NotNull(context, "context");
            if (context.ModelReference == null)
            {
                return(null);
            }

            var apiDataReference = context.ModelReference as ApiDataReference;

            if (apiDataReference == null)
            {
                return(null);
            }

            var entitySet = apiDataReference.Element as IEdmEntitySet;

            if (entitySet == null)
            {
                return(null);
            }

            var entitySetProperty = this.entitySetProperties
                                    .SingleOrDefault(p => p.Name == entitySet.Name);

            if (entitySetProperty != null)
            {
                object target = null;
                if (!entitySetProperty.GetMethod.IsStatic)
                {
                    target = context.QueryContext.ApiContext
                             .GetProperty(typeof(Api).AssemblyQualifiedName);
                    if (target == null ||
                        !this.targetType.IsAssignableFrom(target.GetType()))
                    {
                        return(null);
                    }
                }

                return(entitySetProperty.GetValue(target) as IQueryable);
            }

            return(null);
        }
示例#22
0
        public Expression ReplaceQueryableSource(QueryExpressionContext context, bool embedded)
        {
            var a = new[] { new Product
                            {
                                Id   = 1,
                                Addr = new Address {
                                    Zip = 0001
                                },
                                Addr2 = new Address {
                                    Zip = 0002
                                }
                            } };

            var b = new[] { new Customer
                            {
                                Id = 1,
                            } };

            var c = new[] { new Store
                            {
                                Id = 1,
                            } };

            if (!embedded)
            {
                if (context.VisitedNode.ToString() == "GetQueryableSource(\"Products\", null)")
                {
                    return(Expression.Constant(a.AsQueryable()));
                }

                if (context.VisitedNode.ToString() == "GetQueryableSource(\"Customers\", null)")
                {
                    return(Expression.Constant(b.AsQueryable()));
                }

                if (context.VisitedNode.ToString() == "GetQueryableSource(\"Stores\", null)")
                {
                    return(Expression.Constant(c.AsQueryable()));
                }
            }

            return(context.VisitedNode);
        }
示例#23
0
        private IQueryable GetEntitySetQuery(QueryExpressionContext context)
        {
            Ensure.NotNull(context, "context");
            if (context.ModelReference == null)
            {
                return(null);
            }

            var dataSourceStubReference = context.ModelReference as DataSourceStubModelReference;

            if (dataSourceStubReference == null)
            {
                return(null);
            }

            var entitySet = dataSourceStubReference.Element as IEdmEntitySet;

            if (entitySet == null)
            {
                return(null);
            }

            var entitySetProperty = this.entitySetProperties
                                    .SingleOrDefault(p => p.Name == entitySet.Name);

            if (entitySetProperty != null)
            {
                object target = null;
                if (!entitySetProperty.GetMethod.IsStatic)
                {
                    target = context.QueryContext.GetApiService <ApiBase>();
                    if (target == null ||
                        !this.targetType.IsInstanceOfType(target))
                    {
                        return(null);
                    }
                }

                return(entitySetProperty.GetValue(target) as IQueryable);
            }

            return(null);
        }
        public Expression ReplaceQueryableSource(QueryExpressionContext context, bool embedded)
        {
            var orders = new[]
            {
                new Order {
                    Id = 234
                }
            };

            if (!embedded)
            {
                if (context.VisitedNode.ToString().StartsWith("GetQueryableSource(\"Orders\"", StringComparison.CurrentCulture))
                {
                    return(Expression.Constant(orders.AsQueryable()));
                }
            }

            return(context.VisitedNode);
        }
示例#25
0
            /// <inheritdoc/>
            public Expression ReplaceQueryableSource(QueryExpressionContext context, bool embedded)
            {
                var result = CallInner(context, embedded);

                if (result != null)
                {
                    // Call the provider's sourcer to find the source of the query.
                    return(result);
                }

                // This sourcer ONLY deals with queries that cannot be addressed by the provider
                // such as a singleton query that cannot be sourced by the EF provider, etc.
                var query = ModelCache.GetEntitySetQuery(context) ?? ModelCache.GetSingletonQuery(context);

                if (query != null)
                {
                    return(Expression.Constant(query));
                }

                return(null);
            }
示例#26
0
        /// <inheritdoc/>
        public Expression Source(QueryExpressionContext context, bool embedded)
        {
            var innerHandler = ((IDelegateHookHandler <IQueryExpressionSourcer>) this).InnerHandler;

            if (innerHandler != null)
            {
                var result = innerHandler.Source(context, embedded);
                if (result != null)
                {
                    return(result);
                }
            }

            var query = GetEntitySetQuery(context);

            if (query != null)
            {
                return(Expression.Constant(query));
            }

            return(null);
        }
示例#27
0
        public Expression Source(QueryExpressionContext context, bool embedded)
        {
            var a = new[] { new Product
                            {
                                Id   = 1,
                                Addr = new Address {
                                    Zip = 0001
                                },
                                Addr2 = new Address {
                                    Zip = 0002
                                }
                            } };

            if (!embedded)
            {
                if (context.VisitedNode.ToString() == "Source(\"Products\", null)")
                {
                    return(Expression.Constant(a.AsQueryable()));
                }
            }

            return(context.VisitedNode);
        }
示例#28
0
        /// <summary>
        /// Sources an expression.
        /// </summary>
        /// <param name="context">
        /// The query expression context.
        /// </param>
        /// <param name="embedded">
        /// Indicates if the sourcing is occurring on an embedded node.
        /// </param>
        /// <returns>
        /// A data source expression that represents the visited node.
        /// </returns>
        public Expression Source(QueryExpressionContext context, bool embedded)
        {
            Ensure.NotNull(context, "context");
            var dbContext = context.QueryContext
                            .ApiContext.GetProperty <DbContext>(DbApiConstants.DbContextKey);
            var dbSetProperty = dbContext.GetType().GetProperties()
                                .First(prop => prop.Name == context.ModelReference.EntitySet.Name);

            if (!embedded)
            {
                // TODO GitHubIssue#37 : Add API entity manager for tracking entities
                // the underlying DbContext shouldn't track the entities
                var dbSet = dbSetProperty.GetValue(dbContext);

                ////dbSet = dbSet.GetType().GetMethod("AsNoTracking").Invoke(dbSet, null);
                return(Expression.Constant(dbSet));
            }
            else
            {
                return(Expression.MakeMemberAccess(
                           Expression.Constant(dbContext),
                           dbSetProperty));
            }
        }
示例#29
0
        /// <summary>
        /// Sources an expression.
        /// </summary>
        /// <param name="context">
        /// The query expression context.
        /// </param>
        /// <param name="embedded">
        /// Indicates if the sourcing is occurring on an embedded node.
        /// </param>
        /// <returns>
        /// A data source expression that represents the visited node.
        /// </returns>
        public Expression Source(QueryExpressionContext context, bool embedded)
        {
            Ensure.NotNull(context, "context");

            if (context.ModelReference.EntitySet == null)
            {
                // EF provider can only source *EntitySet*.
                return(null);
            }

            var dbContext     = context.QueryContext.GetApiService <DbContext>();
            var dbSetProperty = dbContext.GetType().GetProperties()
                                .FirstOrDefault(prop => prop.Name == context.ModelReference.EntitySet.Name);

            if (dbSetProperty == null)
            {
                // EF provider can only source EntitySet from *DbSet property*.
                return(null);
            }

            if (!embedded)
            {
                // TODO GitHubIssue#37 : Add API entity manager for tracking entities
                // the underlying DbContext shouldn't track the entities
                var dbSet = dbSetProperty.GetValue(dbContext);

                ////dbSet = dbSet.GetType().GetMethod("AsNoTracking").Invoke(dbSet, null);
                return(Expression.Constant(dbSet));
            }
            else
            {
                return(Expression.MakeMemberAccess(
                           Expression.Constant(dbContext),
                           dbSetProperty));
            }
        }
        /// <inheritdoc/>
        public Expression Process(QueryExpressionContext context)
        {
            Ensure.NotNull(context, nameof(context));

            if (Inner != null)
            {
                var innerFilteredExpression = Inner.Process(context);
                if (innerFilteredExpression != null && innerFilteredExpression != context.VisitedNode)
                {
                    return(innerFilteredExpression);
                }
            }

            if (context.ModelReference is DataSourceStubModelReference dataSourceStubReference)
            {
                if (!(dataSourceStubReference.Element is IEdmEntitySet entitySet))
                {
                    return(null);
                }

                if (!(entitySet.Type is IEdmCollectionType collectionType))
                {
                    return(null);
                }

                if (!(collectionType.ElementType.Definition is IEdmEntityType entityType))
                {
                    return(null);
                }

                return(AppendOnFilterExpression(context, entitySet, entityType));
            }

            if (context.ModelReference is PropertyModelReference propertyModelReference && propertyModelReference.Property != null)
            {
                // Could be a single navigation property or a collection navigation property
                var propType = propertyModelReference.Property.Type;
                if (propType is IEdmCollectionTypeReference collectionTypeReference)
                {
                    var collectionType = collectionTypeReference.Definition as IEdmCollectionType;
                    propType = collectionType.ElementType;
                }

                if (!(propType.Definition is IEdmEntityType entityType))
                {
                    return(null);
                }

                // In case of type inheritance, get the base type
                while (entityType.BaseType != null)
                {
                    entityType = (IEdmEntityType)entityType.BaseType;
                }

                //Get the model, query it for the entity set of a given type.
                var entitySet = context.QueryContext.Model.EntityContainer.EntitySets().FirstOrDefault(c => c.EntityType() == entityType);
                if (entitySet == null)
                {
                    return(null);
                }

                return(AppendOnFilterExpression(context, entitySet, entityType));
            }

            return(null);
        }