Analyze the select clause to determine what parts can be translated fully to HQL, and some other properties of the clause.
Inheritance: System.Linq.Expressions.ExpressionTreeVisitor
Exemplo n.º 1
0
        public void Visit(Expression expression)
        {
            var distinct = expression as NhDistinctExpression;

            if (distinct != null)
            {
                expression = distinct.Expression;
            }

            // Find the sub trees that can be expressed purely in HQL
            var nominator = new SelectClauseHqlNominator(_parameters);

            expression = nominator.Visit(expression);
            _hqlNodes  = nominator.HqlCandidates;

            // Linq2SQL ignores calls to local methods. Linq2EF seems to not support
            // calls to local methods at all. For NHibernate we support local methods,
            // but prevent their use together with server-side distinct, since it may
            // end up being wrong.
            if (distinct != null && nominator.ContainsUntranslatedMethodCalls)
            {
                throw new NotSupportedException("Cannot use distinct on result that depends on methods for which no SQL equivalent exist.");
            }

            // Now visit the tree
            var projection = VisitExpression(expression);

            if ((projection != expression) && !_hqlNodes.Contains(expression))
            {
                ProjectionExpression = Expression.Lambda(projection, _inputParameter);
            }

            // Handle any boolean results in the output nodes
            _hqlTreeNodes = _hqlTreeNodes.ConvertAll(node => node.ToArithmeticExpression());

            if (distinct != null)
            {
                var treeNodes = new List <HqlTreeNode>(_hqlTreeNodes.Count + 1)
                {
                    _hqlTreeBuilder.Distinct()
                };
                treeNodes.AddRange(_hqlTreeNodes);
                _hqlTreeNodes = new List <HqlExpression>(1)
                {
                    _hqlTreeBuilder.ExpressionSubTreeHolder(treeNodes)
                };
            }
        }
		public void Visit(Expression expression)
		{
			var distinct = expression as NhDistinctExpression;
			if (distinct != null)
			{
				expression = distinct.Expression;
			}

			// Find the sub trees that can be expressed purely in HQL
			var nominator = new SelectClauseHqlNominator(_parameters);
			expression = nominator.Visit(expression);
			_hqlNodes = nominator.HqlCandidates;

			// Linq2SQL ignores calls to local methods. Linq2EF seems to not support
			// calls to local methods at all. For NHibernate we support local methods,
			// but prevent their use together with server-side distinct, since it may
			// end up being wrong.
			if (distinct != null && nominator.ContainsUntranslatedMethodCalls)
				throw new NotSupportedException("Cannot use distinct on result that depends on methods for which no SQL equivalent exist.");

			// Now visit the tree
			var projection = VisitExpression(expression);

			if ((projection != expression) && !_hqlNodes.Contains(expression))
			{
				ProjectionExpression = Expression.Lambda(projection, _inputParameter);
			}

			// Handle any boolean results in the output nodes
			_hqlTreeNodes = BooleanToCaseConvertor.Convert(_hqlTreeNodes).ToList();

			if (distinct != null)
			{
				var treeNodes = new List<HqlTreeNode>(_hqlTreeNodes.Count + 1) {_hqlTreeBuilder.Distinct()};
				treeNodes.AddRange(_hqlTreeNodes);
				_hqlTreeNodes = new List<HqlExpression>(1) {_hqlTreeBuilder.ExpressionSubTreeHolder(treeNodes)};
			}
		}