/// <summary>Enumerates create enumerable in this collection.</summary>
        /// <exception cref="Exception">Thrown when an exception error condition occurs.</exception>
        /// <returns>
        ///     An enumerator that allows foreach to be used to process create enumerable in this collection.
        /// </returns>
        public IEnumerable <T> CreateEnumerable()
        {
            if (Childs.Count == 0)
            {
                return(OriginalQueryable);
            }

            IQueryable newQuery = null;
            var        createAnonymousFromQueryMethod = GetType().GetMethod("CreateAnonymousFromQuery");

            foreach (var child in Childs)
            {
                var childQuery = child.CreateIncludeQuery(OriginalQueryable);

                if (newQuery == null)
                {
                    newQuery = OriginalQueryable.Select(x => new { x, child = childQuery });
                }
                else
                {
                    // REFLECTION: newQuery.CreateAnonymousFromQuery<TElement>(newQuery, childQuery);
                    var createAnonymousFromQueryMethodGeneric = createAnonymousFromQueryMethod.MakeGenericMethod(newQuery.ElementType);
                    newQuery = (IQueryable)createAnonymousFromQueryMethodGeneric.Invoke(this, new object[] { newQuery, childQuery });
                }
            }

            // REFLECTION: newQuery.ToList();
            var toListMethod = typeof(Enumerable).GetMethod("ToList").MakeGenericMethod(newQuery.ElementType);
            var toList       = (IEnumerable <object>)toListMethod.Invoke(null, new object[] { newQuery });

            try
            {
                // TODO: Optimize this code
                while (true)
                {
                    toList = toList.Select(x => ((dynamic)x).x).ToList();

                    if (!toList.Any())
                    {
                        return(new List <T>());
                    }
                }
            }
            catch (Exception)
            {
            }

            var list = toList.Cast <T>().ToList();

#if EF6
            // FIX lazy loading
            QueryIncludeFilterLazyLoading.SetLazyLoaded(list, Childs);
#endif

            // FIX null collection
            QueryIncludeFilterNullCollection.NullCollectionToEmpty(list, Childs);


            return(list);
        }
        /// <summary>Executes the given expression.</summary>
        /// <exception cref="Exception">Thrown when an exception error condition occurs.</exception>
        /// <typeparam name="TResult">Type of the result.</typeparam>
        /// <param name="expression">The expression to execute.</param>
        /// <returns>The object returned by the execution of the expression.</returns>
        public TResult Execute <TResult>(Expression expression)
        {
            var methodCall = expression as MethodCallExpression;

            if (methodCall == null)
            {
                throw new Exception(ExceptionMessage.GeneralException);
            }

            if (methodCall.Method.Name == "All" ||
                methodCall.Method.Name == "Any" ||
                methodCall.Method.Name == "Average" ||
                methodCall.Method.Name == "Contains" ||
                methodCall.Method.Name == "Count" ||
                methodCall.Method.Name == "LongCount" ||
                methodCall.Method.Name == "Max" ||
                methodCall.Method.Name == "Min" ||
                methodCall.Method.Name == "SequenceEqual" ||
                methodCall.Method.Name == "Sum")
            {
                return(OriginalProvider.Execute <TResult>(expression));
            }

            var currentQuery  = CurrentQueryable;
            var currentMethod = methodCall.Method.GetGenericMethodDefinition();

            // CHECK if the internal expression can be supported
            var isExpressionSupported = false;

            var firstExpression = methodCall.Arguments.FirstOrDefault(x => x.Type.IsSubclassOf(typeof(Expression)));
            var unaryExpression = firstExpression as UnaryExpression;

            if (firstExpression != null && unaryExpression != null && methodCall.Arguments.Count == 2)
            {
                var lambdaExpression = unaryExpression.Operand as LambdaExpression;

                if (lambdaExpression != null)
                {
                    if (lambdaExpression.Type == typeof(Func <,>).MakeGenericType(currentQuery.ElementType, typeof(bool)))
                    {
                        var method        = typeof(Queryable).GetMethods().First(x => x.Name == "Where" && x.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericArguments().Length == 2);
                        var methodGeneric = method.MakeGenericMethod(currentQuery.ElementType);
                        currentQuery          = (QueryIncludeFilterParentQueryable <T>)methodGeneric.Invoke(null, new object[] { currentQuery, lambdaExpression });
                        currentMethod         = typeof(Queryable).GetMethods().FirstOrDefault(x => x.Name == currentMethod.Name && x.GetParameters().Length == 1);
                        isExpressionSupported = currentMethod != null;
                    }
                }
            }

            if (firstExpression != null && !isExpressionSupported)
            {
                throw new Exception(ExceptionMessage.QueryIncludeFilter_ArgumentExpression);
            }

            // CREATE the new query by selecting included entities in an anonymous type
            var newQuery = currentQuery.CreateQueryable();

            // CREATE a new immediate method from the immediate method used by the user
            var newImmediateMethod = currentMethod.MakeGenericMethod(newQuery.ElementType);

            // REPLACE the first argument with the new query expression
            var arguments = methodCall.Arguments.ToList();

            arguments[0] = newQuery.Expression;

            // REMOVE the last argument if a "Predicate" method was previously used
            if (firstExpression != null)
            {
                arguments.RemoveAt(1);
            }

            // CREATE the new expression
            var newExpression = Expression.Call(null, newImmediateMethod, arguments);

            // EXECUTE the new expression
            var value = OriginalProvider.Execute(newExpression);

            // CHECK if a value has been returned
            if (value == null)
            {
                return((TResult)(object)null);
            }

            // GET the query result from the anonymous type
            var          result = value;
            PropertyInfo property;

            while ((property = result.GetType().GetProperty("x")) != null)
            {
                result = property.GetValue(result, null);
            }

#if EF6
            // FIX lazy loading
            QueryIncludeFilterLazyLoading.SetLazyLoaded(result, currentQuery.Childs);
#endif

            // FIX null collection
            QueryIncludeFilterNullCollection.NullCollectionToEmpty(result, currentQuery.Childs);

            return((TResult)result);
        }