/// <summary> /// Convert and execute a query only if the <see cref="IQueryable"/> expression is not supported by the query provider. /// </summary> /// <param name="query">Query to execute.</param> /// <param name="maxResults">The max number of results allowed in a single transaction against a persistence provider.</param> /// <param name="convertedResult">The result of the query.</param> /// <param name="numberOfTempResults">The number of temporary results that should be combined.</param> /// <returns>A <see cref="bool"/> that specify if the query was converted and executed.</returns> public static bool ConvertionIsRequiredAsExpressionIfNotSupported(IQueryable query, int maxResults, out object convertedResult, out int numberOfTempResults) { var vistor = new MethodExpressionsMarker(); var methodsNames = vistor.Eval(query.Expression); var providerName = query.Provider.GetType().Name; numberOfTempResults = 1; List <string> knownUnsupportedFunctions; if (unsupportedMethodsPerProvider.TryGetValue(providerName, out knownUnsupportedFunctions)) { if (knownUnsupportedFunctions.Intersect(methodsNames).Count() > 0) { var adapter = new QueriableProviderAdapter() { Provider = query.Provider, MaxCollectionSize = maxResults }; convertedResult = adapter.Eval(query.Expression, out numberOfTempResults); return(true); } } try { var enumerator = query.GetEnumerator(); enumerator.MoveNext(); convertedResult = null; return(false); } catch (NotSupportedException ex) { var unsupportedMethod = ex.Message.Split(' ').Intersect(methodsNames).FirstOrDefault(); if (!string.IsNullOrEmpty(unsupportedMethod)) { unsupportedMethodsPerProvider.AddOrUpdate( providerName, (_) => new List <string>() { unsupportedMethod }, (_, lst) => { lst.Add(unsupportedMethod); return(lst); }); } var adapter = new QueriableProviderAdapter() { Provider = query.Provider, MaxCollectionSize = maxResults }; convertedResult = adapter.Eval(query.Expression, out numberOfTempResults); return(true); } }
/// <summary> /// Execute the query. If it is not supported by the underlying query provider, transform it to be executed on a memory collection. /// </summary> /// <typeparam name="TResult">Type of the result.</typeparam> /// <param name="expression">The expression tree to execute.</param> /// <returns>The expression execution result.</returns> public TResult Execute <TResult>(Expression expression) { try { return(this._underlyingProvider.Execute <TResult>(this.InterceptExpr(expression))); } catch (NotSupportedException) { var adapter = new QueriableProviderAdapter() { Provider = this._underlyingProvider, MaxCollectionSize = this.MaxResults }; var res = adapter.Eval <TResult>(expression, this.Combiner); return(res); } }
/// <summary> /// Execute the query. If it is not supported by the underlying query provider, transform it to be executed on a memory collection. /// </summary> /// <param name="expression">The expression tree to execute.</param> /// <returns>The expression execution result.</returns> public object Execute(Expression expression) { try { return(this._underlyingProvider.Execute(InterceptExpr(expression))); } catch (NotSupportedException) { var adapter = new QueriableProviderAdapter() { Provider = _underlyingProvider, MaxCollectionSize = MaxResults }; int numberOfTempResults; var res = adapter.Eval(expression, out numberOfTempResults, Combiner); return(res); } }