/// <summary>
    /// Modifies the given query model for fetching, adding an <see cref="AdditionalFromClause"/> and changing the <see cref="SelectClause.Selector"/> to 
    /// retrieve the result of the <see cref="AdditionalFromClause"/>.
    /// For example, a fetch request such as <c>FetchMany (x => x.Orders)</c> will be transformed into a <see cref="AdditionalFromClause"/> selecting
    /// <c>y.Orders</c> (where <c>y</c> is what the query model originally selected) and a <see cref="SelectClause"/> selecting the result of the
    /// <see cref="AdditionalFromClause"/>.
    /// This method is called by <see cref="FetchRequestBase.CreateFetchQueryModel"/> in the process of creating the new fetch query model.
    /// </summary>
    protected override void ModifyFetchQueryModel (QueryModel fetchQueryModel)
    {
      ArgumentUtility.CheckNotNull ("fetchQueryModel", fetchQueryModel);

      var fromExpression = GetFetchedMemberExpression (new QuerySourceReferenceExpression (fetchQueryModel.MainFromClause));
      var memberFromClause = new AdditionalFromClause (fetchQueryModel.GetNewName ("#fetch"), _relatedObjectType, fromExpression);
      fetchQueryModel.BodyClauses.Add (memberFromClause);

      var newSelector = new QuerySourceReferenceExpression (memberFromClause);
      var newSelectClause = new SelectClause (newSelector);
      fetchQueryModel.SelectClause = newSelectClause;
    }
    /// <summary>
    /// Replaces the given parameter with a back-reference to the <see cref="IQuerySource"/> corresponding to <paramref name="referencedNode"/>.
    /// </summary>
    /// <param name="referencedNode">The referenced node.</param>
    /// <param name="parameterToReplace">The parameter to replace with a <see cref="QuerySourceReferenceExpression"/>.</param>
    /// <param name="expression">The expression in which to replace the parameter.</param>
    /// <param name="context">The clause generation context.</param>
    /// <returns><paramref name="expression"/>, with <paramref name="parameterToReplace"/> replaced with a <see cref="QuerySourceReferenceExpression"/>
    /// pointing to the clause corresponding to <paramref name="referencedNode"/>.</returns>
    public static Expression ReplaceParameterWithReference (
        IQuerySourceExpressionNode referencedNode, 
        ParameterExpression parameterToReplace, 
        Expression expression, 
        ClauseGenerationContext context)
    {
      ArgumentUtility.CheckNotNull ("referencedNode", referencedNode);
      ArgumentUtility.CheckNotNull ("parameterToReplace", parameterToReplace);
      ArgumentUtility.CheckNotNull ("expression", expression);
      ArgumentUtility.CheckNotNull ("context", context);

      var clause = GetQuerySourceForNode (referencedNode, context);
      var referenceExpression = new QuerySourceReferenceExpression (clause);

      return ReplacingExpressionTreeVisitor.Replace (parameterToReplace, referenceExpression, expression);
    }
    protected override Expression VisitQuerySourceReferenceExpression (QuerySourceReferenceExpression expression)
    {
      ArgumentUtility.CheckNotNull ("expression", expression);

      if (QuerySourceMapping.ContainsMapping (expression.ReferencedQuerySource))
      {
        return QuerySourceMapping.GetExpression (expression.ReferencedQuerySource);
      }
      else if (_throwOnUnmappedReferences)
      {
        var message = "Cannot replace reference to clause '" + expression.ReferencedQuerySource.ItemName + "', there is no mapped expression.";
        throw new InvalidOperationException (message);
      }
      else
      {
        return expression;
      }
    }
 protected override Expression VisitQuerySourceReferenceExpression (QuerySourceReferenceExpression expression)
 {
   ArgumentUtility.CheckNotNull ("expression", expression);
   return Expression.Parameter (expression.Type, "[" + expression.ReferencedQuerySource.ItemName + "]");
 }
    protected override Expression VisitQuerySourceReferenceExpression (QuerySourceReferenceExpression expression)
    {
      ArgumentUtility.CheckNotNull ("expression", expression);

      try
      {
        var accessorLambda = AccessorFindingExpressionTreeVisitor.FindAccessorLambda (expression, _itemExpression, _lambdaParameter);
        return accessorLambda.Body;
      }
      catch (ArgumentException ex)
      {
        var message = string.Format (
            "Cannot create a LambdaExpression that retrieves the value of '{0}' from items with a structure of '{1}'. The item expression does not "
            + "contain the value or it is too complex.",
            FormattingExpressionTreeVisitor.Format (expression),
            FormattingExpressionTreeVisitor.Format (_itemExpression));
        throw new InvalidOperationException (message, ex);
      }
    }