Пример #1
0
        private void AddIncludedProperty(Expression root, ReferencedRelatedObject referencedRelatedObject, PropertyPath prefixPath)
        {
            for (var i = 0; i < referencedRelatedObject.IncludedPropertyPath.Length + prefixPath.Length; i++)
            {
                var fullAccessPropertyPath = new PropertyPath(c => c.Name, referencedRelatedObject.FullAccessPropertyPath.Take(referencedRelatedObject.FullAccessPropertyPath.Length - i));
                var currentPropertyPath    = new PropertyPath(c => c.Name, prefixPath.Concat(referencedRelatedObject.IncludedPropertyPath.Take(referencedRelatedObject.IncludedPropertyPath.Length - i)));

                var includedPropertyInfo = new IncludedPropertyInfo
                {
                    RootExpression         = root,
                    FullAccessPropertyPath = fullAccessPropertyPath,
                    IncludedPropertyPath   = currentPropertyPath
                };

                this.includedPropertyInfos.Add(includedPropertyInfo);
            }
        }
        private void AddIncludedProperty(Expression root, ReferencedRelatedObject referencedRelatedObject, PropertyPath prefixPath)
        {
            var fullAccessPropertyPath = new PropertyPath(c => c.Name, referencedRelatedObject.FullAccessPropertyPath);
            var currentPropertyPath    = new PropertyPath(c => c.Name, prefixPath.Concat(referencedRelatedObject.IncludedPropertyPath));

            while (currentPropertyPath.Length > 0)
            {
                var includedPropertyInfo = new IncludedPropertyInfo
                {
                    RootExpression         = root,
                    FullAccessPropertyPath = fullAccessPropertyPath,
                    IncludedPropertyPath   = currentPropertyPath
                };

                this.includedPropertyInfos.Add(includedPropertyInfo);

                fullAccessPropertyPath = fullAccessPropertyPath.RemoveLast();
                currentPropertyPath    = currentPropertyPath.RemoveLast();
            }
        }
        private void AddIncludedProperty(Expression root, ReferencedRelatedObject referencedRelatedObject, PropertyPath prefixPath)
        {
            for (var i = 0; i < referencedRelatedObject.IncludedPropertyPath.Length + prefixPath.Length; i++)
            {
                var fullAccessPropertyPath = new PropertyPath(c => c.Name, referencedRelatedObject.FullAccessPropertyPath.Take(referencedRelatedObject.FullAccessPropertyPath.Length - i));
                var currentPropertyPath = new PropertyPath(c => c.Name, prefixPath.Concat(referencedRelatedObject.IncludedPropertyPath.Take(referencedRelatedObject.IncludedPropertyPath.Length - i)));

                var includedPropertyInfo = new IncludedPropertyInfo
                {
                    RootExpression = root,
                    FullAccessPropertyPath = fullAccessPropertyPath,
                    IncludedPropertyPath = currentPropertyPath
                };

                this.includedPropertyInfos.Add(includedPropertyInfo);
            }
        }
        protected override Expression VisitMemberAccess(MemberExpression memberExpression)
        {
            MemberExpression expression;
            var visited = new List<MemberExpression>();
            var root = memberExpression.Expression;
            var memberIsDataAccessObjectGatheringForProjection = false;

            if (memberExpression.Type.IsDataAccessObjectType())
            {
                if (this.forProjection)
                {
                    memberIsDataAccessObjectGatheringForProjection = true;

                    expression = memberExpression;
                }
                else
                {
                    return memberExpression;
                }
            }
            else
            {
                if (memberExpression.Expression == null)
                {
                    return memberExpression;
                }

                var typeDescriptor = this.model.TypeDescriptorProvider.GetTypeDescriptor(memberExpression.Expression.Type);

                if (typeDescriptor == null)
                {
                    return memberExpression;
                }

                var property = typeDescriptor.GetPropertyDescriptorByPropertyName(memberExpression.Member.Name);

                if (property.IsPrimaryKey && memberExpression.Expression is MemberExpression)
                {
                    expression = ((MemberExpression) memberExpression.Expression).Expression as MemberExpression;
                }
                else
                {
                    expression = memberExpression.Expression as MemberExpression;
                }
            }

            var currentExpression = expression;

            while (currentExpression != null && currentExpression.Member is PropertyInfo)
            {
                visited.Add(currentExpression);

                root = currentExpression.Expression;
                currentExpression = root as MemberExpression;
            }

            var includedPathSkip = 0;

            var i = 0;

            foreach (var current in visited)
            {
                if (!current.Member.ReflectedType.IsDataAccessObjectType()
                    || current == this.currentParent /* @see: Test_Select_Project_Related_Object_And_Include1 */)
                {
                    root = current;
                    includedPathSkip = visited.Count - i;

                    break;
                }

                i++;
            }

            visited.Reverse();

            i = 0;
            currentExpression = expression;

            while (currentExpression != null && currentExpression.Member is PropertyInfo)
            {
                var path = new PropertyPath(c => c.Name, visited.Select(c=> (PropertyInfo)c.Member).Take(visited.Count - i).ToArray());
                var expressionPath = visited.Take(visited.Count - i).ToArray();

                ReferencedRelatedObject objectInfo;

                if (path.Length == 0)
                {
                    break;
                }

                if (!path.Last.ReflectedType.IsDataAccessObjectType())
                {
                    this.rootExpressionsByPath[path] = currentExpression;

                    break;
                }

                if (!this.results.TryGetValue(path, out objectInfo))
                {
                    var x = i + includedPathSkip - 1;
                    var includedPropertyPath = new PropertyPath(c => c.Name, path.Skip(includedPathSkip));
                    var objectExpression = x >= 0 ? visited[x] : root;

                    objectInfo = new ReferencedRelatedObject(path, includedPropertyPath, objectExpression);

                    this.results[path] = objectInfo;
                }

                this.referencedRelatedObjects.Add(objectInfo);

                if (memberIsDataAccessObjectGatheringForProjection)
                {
                    objectInfo.TargetExpressions.Add(currentExpression);
                }
                else if (currentExpression == expression)
                {
                    objectInfo.TargetExpressions.Add(expression);
                }

                i++;
                currentExpression = currentExpression.Expression as MemberExpression;
            }

            return memberExpression;
        }
        protected override Expression VisitMemberAccess(MemberExpression memberExpression)
        {
            MemberExpression expression;
            var visited = new List <MemberExpression>();
            var root    = memberExpression.Expression.StripItemsCalls();
            var memberIsDataAccessObjectGatheringForProjection = false;

            // Don't perform implicit joins for RelatedDataAccessObject collections as those currently turn into N+1 queries

            if (this.nesting < 1 && (memberExpression.Type.GetSequenceElementType()?.IsDataAccessObjectType() ?? false))
            {
                return(base.VisitMemberAccess(memberExpression));
            }

            if (memberExpression.Type.IsTypeRequiringJoin())
            {
                if (this.forProjection)
                {
                    memberIsDataAccessObjectGatheringForProjection = true;

                    expression = memberExpression.StripItemsCalls() as MemberExpression;
                }
                else
                {
                    expression = memberExpression.Expression.StripItemsCalls() as MemberExpression;

                    if (expression == null || !expression.Expression.StripItemsCalls().Type.IsTypeRequiringJoin())
                    {
                        return(memberExpression);
                    }
                }
            }
            else
            {
                if (memberExpression.Expression?.StripItemsCalls() == null)
                {
                    return(memberExpression);
                }

                var typeDescriptor = this.model.TypeDescriptorProvider.GetTypeDescriptor(memberExpression.Expression.StripItemsCalls().Type);

                if (typeDescriptor == null)
                {
                    return(Expression.MakeMemberAccess(Visit(memberExpression.Expression.StripItemsCalls()), memberExpression.Member));
                }

                var property = typeDescriptor.GetPropertyDescriptorByPropertyName(memberExpression.Member.Name);

                if (property.IsPrimaryKey && memberExpression.Expression.StripItemsCalls() is MemberExpression)
                {
                    expression = ((MemberExpression)memberExpression.Expression.StripItemsCalls()).Expression.StripItemsCalls() as MemberExpression;
                }
                else
                {
                    expression = memberExpression.Expression.StripItemsCalls() as MemberExpression;
                }
            }

            var currentMemberExpression = expression.StripItemsCalls() as MemberExpression;

            while (currentMemberExpression?.Member is PropertyInfo)
            {
                visited.Add(currentMemberExpression);

                root = GetExpression(currentMemberExpression.Expression).StripItemsCalls();

                currentMemberExpression = root as MemberExpression;
            }

            if (root.Type != this.sourceParameterExpression.Type)
            {
                return(memberExpression);
            }

            var includedPathSkip = 0;

            var i = 0;

            foreach (var current in visited)
            {
                if (!current.Member.ReflectedType.IsTypeRequiringJoin() ||
                    current == this.currentParent /* @see: Test_Select_Project_Related_Object_And_Include1 */)
                {
                    includedPathSkip = visited.Count - i;

                    break;
                }

                i++;
            }

            visited.Reverse();

            if (root.StripPropertiesAndIncludeExtensions() != this.sourceParameterExpression)
            {
                return(memberExpression);
            }

            i = 0;
            currentMemberExpression = expression;

            while (currentMemberExpression?.Member is PropertyInfo)
            {
                var path = new PropertyPath(c => c.Name, visited.Select(c => (PropertyInfo)c.Member).Take(visited.Count - i).ToArray());

                if (path.Length == 0)
                {
                    break;
                }

                if (!path.Last.ReflectedType.IsTypeRequiringJoin())
                {
                    this.rootExpressionsByPath[path] = currentMemberExpression;

                    break;
                }

                if (!this.results.TryGetValue(path, out var objectInfo))
                {
                    var includedPropertyPath = new PropertyPath(c => c.Name, path.Skip(includedPathSkip));

                    objectInfo = new ReferencedRelatedObject(path, includedPropertyPath, this.sourceParameterExpression);

                    this.results[path] = objectInfo;
                }

                this.referencedRelatedObjects.Add(objectInfo);

                if (memberIsDataAccessObjectGatheringForProjection)
                {
                    objectInfo.TargetExpressions.Add(currentMemberExpression);
                }
                else if (currentMemberExpression == expression)
                {
                    objectInfo.TargetExpressions.Add(expression);
                }

                i++;
                currentMemberExpression = currentMemberExpression.Expression.StripItemsCalls() as MemberExpression;
            }

            return(memberExpression);
        }
		protected override Expression VisitMemberAccess(MemberExpression memberExpression)
		{
			MemberExpression expression; 
			var visited = new List<MemberExpression>();
			var root = memberExpression.Expression.StripForIncludeScanning();
			var memberIsDataAccessObjectGatheringForProjection = false;

			// Don't perform implicit joins for RelatedDataAccessObject collections as those currently turn into N+1 queries
			if (this.nesting < 1 && (memberExpression.Type.GetSequenceElementType()?.IsDataAccessObjectType() ?? false))
			{
				return base.VisitMemberAccess(memberExpression);
			}
			
			if (memberExpression.Type.IsTypeRequiringJoin())
			{
				if (this.forProjection)
				{
					memberIsDataAccessObjectGatheringForProjection = true;

					expression = memberExpression.StripForIncludeScanning() as MemberExpression;
				}
				else
				{
					expression = memberExpression.Expression.StripForIncludeScanning() as MemberExpression;

					if (expression == null || !expression.Expression.StripForIncludeScanning().Type.IsTypeRequiringJoin())
					{
						return memberExpression;
					}
				}
			}
			else
			{
				if (memberExpression.Expression?.StripForIncludeScanning() == null)
				{
					return memberExpression;
				}

				var typeDescriptor = this.model.TypeDescriptorProvider.GetTypeDescriptor(memberExpression.Expression.StripForIncludeScanning().Type);

				if (typeDescriptor == null)
				{
					return Expression.MakeMemberAccess(this.Visit(memberExpression.Expression.StripForIncludeScanning()), memberExpression.Member);
				}

				var property = typeDescriptor.GetPropertyDescriptorByPropertyName(memberExpression.Member.Name);

				if (property.IsPrimaryKey && memberExpression.Expression.StripForIncludeScanning() is MemberExpression)
				{
					expression = ((MemberExpression)memberExpression.Expression.StripForIncludeScanning()).Expression.StripForIncludeScanning() as MemberExpression;
				}
				else
				{
					expression = memberExpression.Expression.StripForIncludeScanning() as MemberExpression;
				}
			}

			var currentExpression = expression.StripForIncludeScanning() as MemberExpression;

			while (currentExpression?.Member is PropertyInfo)
			{
				visited.Add(currentExpression);

				root = currentExpression.Expression.StripForIncludeScanning();

				currentExpression = root as MemberExpression;

				if (currentExpression == null)
				{
					root = this.GetExpression(root).StripForIncludeScanning();
					currentExpression = root as MemberExpression;
				}
			}

			var includedPathSkip = 0;

			var i = 0;

			foreach (var current in visited)
			{
				if (!current.Member.ReflectedType.IsTypeRequiringJoin()
					|| current == this.currentParent /* @see: Test_Select_Project_Related_Object_And_Include1 */)
				{
					includedPathSkip = visited.Count - i;
					
					break;
				}

				i++;
			}

			visited.Reverse();

			i = 0;
			currentExpression = expression;

			while (currentExpression?.Member is PropertyInfo)
			{
				var path = new PropertyPath(c => c.Name, visited.Select(c=> (PropertyInfo)c.Member).Take(visited.Count - i).ToArray());
				
				ReferencedRelatedObject objectInfo;

				if (path.Length == 0)
				{
					break;
				}

				if (!path.Last.ReflectedType.IsTypeRequiringJoin())
				{
					this.rootExpressionsByPath[path] = currentExpression;
					
					break;
				}

				if (!this.results.TryGetValue(path, out objectInfo))
				{
					var includedPropertyPath = new PropertyPath(c => c.Name, path.Skip(includedPathSkip));

					objectInfo = new ReferencedRelatedObject(path, includedPropertyPath, sourceParameterExpression);

					this.results[path] = objectInfo;
				}

				this.referencedRelatedObjects.Add(objectInfo);

				if (memberIsDataAccessObjectGatheringForProjection)
				{
					objectInfo.TargetExpressions.Add(currentExpression);
				}
				else if (currentExpression == expression)
				{
					objectInfo.TargetExpressions.Add(expression);
				}

				i++;
				currentExpression = currentExpression.Expression.StripForIncludeScanning() as MemberExpression;
			}

			return memberExpression;
		}
		private void AddIncludedProperty(Expression root, ReferencedRelatedObject referencedRelatedObject, PropertyPath prefixPath)
		{
			var fullAccessPropertyPath = new PropertyPath(c => c.Name, referencedRelatedObject.FullAccessPropertyPath);
			var currentPropertyPath = new PropertyPath(c => c.Name, prefixPath.Concat(referencedRelatedObject.IncludedPropertyPath));
			
			while (currentPropertyPath.Length > 0)
			{
				var includedPropertyInfo = new IncludedPropertyInfo
				{
					RootExpression = root,
					FullAccessPropertyPath = fullAccessPropertyPath,
					IncludedPropertyPath = currentPropertyPath
				};

				this.includedPropertyInfos.Add(includedPropertyInfo);

				fullAccessPropertyPath = fullAccessPropertyPath.RemoveLast();
				currentPropertyPath = currentPropertyPath.RemoveLast();
			}
		}
Пример #8
0
        protected override Expression VisitMemberAccess(MemberExpression memberExpression)
        {
            MemberExpression expression;
            var visited = new List <MemberExpression>();
            var root    = memberExpression.Expression;
            var memberIsDataAccessObjectGatheringForProjection = false;

            if (memberExpression.Type.IsDataAccessObjectType())
            {
                if (this.forProjection)
                {
                    memberIsDataAccessObjectGatheringForProjection = true;

                    expression = memberExpression;
                }
                else
                {
                    return(memberExpression);
                }
            }
            else
            {
                if (memberExpression.Expression == null)
                {
                    return(memberExpression);
                }

                var typeDescriptor = this.model.TypeDescriptorProvider.GetTypeDescriptor(memberExpression.Expression.Type);

                if (typeDescriptor == null)
                {
                    return(memberExpression);
                }

                var property = typeDescriptor.GetPropertyDescriptorByPropertyName(memberExpression.Member.Name);

                if (property.IsPrimaryKey && memberExpression.Expression is MemberExpression)
                {
                    expression = ((MemberExpression)memberExpression.Expression).Expression as MemberExpression;
                }
                else
                {
                    expression = memberExpression.Expression as MemberExpression;
                }
            }

            var currentExpression = expression;

            while (currentExpression != null && currentExpression.Member is PropertyInfo)
            {
                visited.Add(currentExpression);

                root = currentExpression.Expression;
                currentExpression = root as MemberExpression;
            }

            var includedPathSkip = 0;

            var i = 0;

            foreach (var current in visited)
            {
                if (!current.Member.ReflectedType.IsDataAccessObjectType() ||
                    current == this.currentParent /* @see: Test_Select_Project_Related_Object_And_Include1 */)
                {
                    root             = current;
                    includedPathSkip = visited.Count - i;

                    break;
                }

                i++;
            }

            visited.Reverse();

            i = 0;
            currentExpression = expression;

            while (currentExpression != null && currentExpression.Member is PropertyInfo)
            {
                var path           = new PropertyPath(c => c.Name, visited.Select(c => (PropertyInfo)c.Member).Take(visited.Count - i).ToArray());
                var expressionPath = visited.Take(visited.Count - i).ToArray();

                ReferencedRelatedObject objectInfo;

                if (path.Length == 0)
                {
                    break;
                }

                if (!path.Last.ReflectedType.IsDataAccessObjectType())
                {
                    this.rootExpressionsByPath[path] = currentExpression;

                    break;
                }

                if (!this.results.TryGetValue(path, out objectInfo))
                {
                    var x = i + includedPathSkip - 1;
                    var includedPropertyPath = new PropertyPath(c => c.Name, path.Skip(includedPathSkip));
                    var objectExpression     = x >= 0 ? visited[x] : root;

                    objectInfo = new ReferencedRelatedObject(path, includedPropertyPath, objectExpression);

                    this.results[path] = objectInfo;
                }

                this.referencedRelatedObjects.Add(objectInfo);

                if (memberIsDataAccessObjectGatheringForProjection)
                {
                    objectInfo.TargetExpressions.Add(currentExpression);
                }
                else if (currentExpression == expression)
                {
                    objectInfo.TargetExpressions.Add(expression);
                }

                i++;
                currentExpression = currentExpression.Expression as MemberExpression;
            }

            return(memberExpression);
        }