internal static Expression Bind(DataAccessModel dataAccessModel, SqlDataTypeProvider sqlDataTypeProvider, Expression expression) { var placeholderCount = -1; expression = Evaluator.PartialEval(expression, ref placeholderCount); expression = QueryBinder.Bind(dataAccessModel, expression); expression = SqlEnumTypeNormalizer.Normalize(expression, sqlDataTypeProvider.GetTypeForEnums()); expression = Evaluator.PartialEval(expression, ref placeholderCount); expression = SqlNullComparisonCoalescer.Coalesce(expression); expression = SqlTupleOrAnonymousTypeComparisonExpander.Expand(expression); expression = SqlObjectOperandComparisonExpander.Expand(expression); expression = SqlRedundantFunctionCallRemover.Remove(expression); return(expression); }
public static Expression Optimize(Expression expression, Type typeForEnums, bool simplerPartialVal = true) { expression = SqlObjectOperandComparisonExpander.Expand(expression); expression = SqlEnumTypeNormalizer.Normalize(expression, typeForEnums); expression = SqlGroupByCollator.Collate(expression); expression = SqlAggregateSubqueryRewriter.Rewrite(expression); expression = SqlUnusedColumnRemover.Remove(expression); expression = SqlRedundantColumnRemover.Remove(expression); expression = SqlRedundantSubqueryRemover.Remove(expression); expression = SqlFunctionCoalescer.Coalesce(expression); expression = SqlExistsSubqueryOptimizer.Optimize(expression); expression = SqlRedundantBinaryExpressionsRemover.Remove(expression); expression = SqlCrossJoinRewriter.Rewrite(expression); if (simplerPartialVal) { expression = Evaluator.PartialEval(expression, c => c.NodeType != (ExpressionType)SqlExpressionType.ConstantPlaceholder && Evaluator.CanBeEvaluatedLocally(c)); } else { expression = Evaluator.PartialEval(expression); } expression = SqlRedundantFunctionCallRemover.Remove(expression); expression = SqlConditionalEliminator.Eliminate(expression); expression = SqlExpressionCollectionOperationsExpander.Expand(expression); expression = SqlSumAggregatesDefaultValueCoalescer.Coalesce(expression); expression = SqlOrderByRewriter.Rewrite(expression); var rewritten = SqlCrossApplyRewriter.Rewrite(expression); if (rewritten != expression) { expression = rewritten; expression = SqlUnusedColumnRemover.Remove(expression); expression = SqlRedundantColumnRemover.Remove(expression); expression = SqlRedundantSubqueryRemover.Remove(expression); expression = SqlOrderByRewriter.Rewrite(expression); } return(expression); }
private PrivateExecuteResult <T> PrivateExecute <T>(Expression expression) { var projectionExpression = expression as SqlProjectionExpression; if (projectionExpression == null) { expression = Evaluator.PartialEval(expression); if (this.RelatedDataAccessObjectContext == null) { expression = QueryBinder.Bind(this.DataAccessModel, expression, null, null); } else { expression = QueryBinder.Bind(this.DataAccessModel, expression, this.RelatedDataAccessObjectContext.ElementType, this.RelatedDataAccessObjectContext.ExtraCondition); } projectionExpression = (SqlProjectionExpression)Optimize(expression, this.SqlDatabaseContext.SqlDataTypeProvider.GetTypeForEnums(), true); } ProjectorCacheInfo cacheInfo; var columns = projectionExpression.Select.Columns.Select(c => c.Name); var formatResult = this.SqlDatabaseContext.SqlQueryFormatterManager.Format(projectionExpression, SqlQueryFormatterOptions.Default); var placeholderValues = PlaceholderValuesCollector.CollectValues(expression); var key = new ProjectorCacheKey(projectionExpression, this.SqlDatabaseContext); var projectorCache = this.SqlDatabaseContext.projectorCache; if (!projectorCache.TryGetValue(key, out cacheInfo)) { var projectionLambda = ProjectionBuilder.Build(this.DataAccessModel, this.SqlDatabaseContext, projectionExpression.Projector, columns); cacheInfo.elementType = projectionLambda.Body.Type; cacheInfo.projector = projectionLambda.Compile(); var aggregates = AggregateFinder.Find(projectionExpression); if (aggregates.Count == 1) { cacheInfo.sqlAggregateType = aggregates.First().AggregateType; } var newCache = new Dictionary <ProjectorCacheKey, ProjectorCacheInfo>(projectorCache, ProjectorCacheEqualityComparer.Default); if (!projectorCache.ContainsKey(key)) { newCache[key] = cacheInfo; } this.SqlDatabaseContext.projectorCache = newCache; } var elementType = TypeHelper.GetElementType(cacheInfo.elementType); var concreteElementType = elementType; if (elementType.IsDataAccessObjectType()) { Type type; TypeHelper.GetElementType(cacheInfo.elementType); elementType = this.DataAccessModel.GetDefinitionTypeFromConcreteType(elementType); concreteElementType = this.DataAccessModel.GetConcreteTypeFromDefinitionType(elementType); if (this.RelatedDataAccessObjectContext == null) { type = typeof(DataAccessObjectProjector <,>); } else { type = typeof(RelatedDataAccessObjectProjector <,>); } return(new PrivateExecuteResult <T> ( (IEnumerable <T>)Activator.CreateInstance ( type.MakeGenericType(elementType, concreteElementType), this, this.DataAccessModel, formatResult, this.SqlDatabaseContext, cacheInfo.projector, this.RelatedDataAccessObjectContext, projectionExpression.SelectFirstType, cacheInfo.sqlAggregateType, projectionExpression.IsDefaultIfEmpty, placeholderValues ), projectionExpression.SelectFirstType, cacheInfo.sqlAggregateType, projectionExpression.IsDefaultIfEmpty, projectionExpression.DefaultValueExpression )); } else { return(new PrivateExecuteResult <T> ( (IEnumerable <T>)Activator.CreateInstance ( typeof(ObjectProjector <,>).MakeGenericType(elementType, concreteElementType), this, this.DataAccessModel, formatResult, this.SqlDatabaseContext, cacheInfo.projector, this.RelatedDataAccessObjectContext, projectionExpression.SelectFirstType, cacheInfo.sqlAggregateType, projectionExpression.IsDefaultIfEmpty, placeholderValues ), projectionExpression.SelectFirstType, cacheInfo.sqlAggregateType, projectionExpression.IsDefaultIfEmpty, projectionExpression.DefaultValueExpression )); } }