Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        public static void DeleteWhere <T>(this DataAccessObjectsQueryable <T> queryable, Expression <Func <T, bool> > condition)
            where T : DataAccessObject
        {
            queryable.DataAccessModel.Flush();

            var transactionContext = queryable.DataAccessModel.AmbientTransactionManager.GetCurrentContext(true);

            using (var acquisition = transactionContext.AcquirePersistenceTransactionContext(queryable.DataAccessModel.GetCurrentSqlDatabaseContext()))
            {
                var expression = (Expression)Expression.Call(null, MethodCache <T> .DeleteMethod, Expression.Constant(queryable, typeof(DataAccessObjectsQueryable <T>)), condition);

                expression = Evaluator.PartialEval(expression);
                expression = QueryBinder.Bind(queryable.DataAccessModel, expression, queryable.ElementType, queryable.ExtraCondition);
                expression = SqlObjectOperandComparisonExpander.Expand(expression);
                expression = SqlQueryProvider.Optimize(expression, transactionContext.SqlDatabaseContext.SqlDataTypeProvider.GetTypeForEnums());

                acquisition.SqlDatabaseCommandsContext.Delete((SqlDeleteExpression)expression);
            }
        }
Exemple #4
0
        public override void Delete(Type type, IEnumerable <DataAccessObject> dataAccessObjects)
        {
            var typeDescriptor = this.DataAccessModel.GetTypeDescriptor(type);
            var parameter      = Expression.Parameter(typeDescriptor.Type, "value");

            Expression body = null;

            foreach (var dataAccessObject in dataAccessObjects)
            {
                var currentExpression = Expression.Equal(parameter, Expression.Constant(dataAccessObject));

                if (body == null)
                {
                    body = currentExpression;
                }
                else
                {
                    body = Expression.OrElse(body, currentExpression);
                }
            }

            if (body == null)
            {
                return;
            }

            var condition  = Expression.Lambda(body, parameter);
            var expression = (Expression)Expression.Call(null, GetDeleteMethod(typeDescriptor.Type), Expression.Constant(null, typeDescriptor.Type), condition);

            expression = Evaluator.PartialEval(expression);
            expression = QueryBinder.Bind(this.DataAccessModel, expression, null, null);
            expression = SqlObjectOperandComparisonExpander.Expand(expression);
            expression = SqlQueryProvider.Optimize(expression, this.SqlDatabaseContext.SqlDataTypeProvider.GetTypeForEnums());

            this.Delete((SqlDeleteExpression)expression);
        }
Exemple #5
0
        protected virtual IDbCommand BuildUpdateCommand(TypeDescriptor typeDescriptor, DataAccessObject dataAccessObject)
        {
            bool       valuesPredicated;
            bool       primaryKeysPredicated;
            IDbCommand command = null;
            SqlCachedUpdateInsertFormatValue cachedValue;
            var requiresIdentityInsert = dataAccessObject.ToObjectInternal().HasAnyChangedPrimaryKeyServerSideProperties;
            var updatedProperties      = dataAccessObject.ToObjectInternal().GetChangedPropertiesFlattened(out valuesPredicated);

            if (updatedProperties.Count == 0)
            {
                return(null);
            }

            var success     = false;
            var primaryKeys = dataAccessObject.ToObjectInternal().GetPrimaryKeysForUpdateFlattened(out primaryKeysPredicated);

            if (valuesPredicated || primaryKeysPredicated)
            {
                return(BuildUpdateCommandForDeflatedPredicated(typeDescriptor, dataAccessObject, valuesPredicated, primaryKeysPredicated, updatedProperties, primaryKeys));
            }

            var commandKey = new SqlCachedUpdateInsertFormatKey(dataAccessObject.GetType(), updatedProperties, requiresIdentityInsert);

            if (this.TryGetUpdateCommand(commandKey, out cachedValue))
            {
                try
                {
                    command             = this.CreateCommand();
                    command.CommandText = cachedValue.formatResult.CommandText;

                    this.FillParameters(command, cachedValue, updatedProperties, primaryKeys);

                    success = true;

                    return(command);
                }
                finally
                {
                    if (!success)
                    {
                        command?.Dispose();
                    }
                }
            }

            var constantPlaceholdersCount = 0;
            var valueIndexesToParameterPlaceholderIndexes      = new int[updatedProperties.Count];
            var primaryKeyIndexesToParameterPlaceholderIndexes = new int[primaryKeys.Length];

            var assignments = new List <Expression>(updatedProperties.Count);

            foreach (var updated in updatedProperties)
            {
                var value = (Expression) new SqlConstantPlaceholderExpression(constantPlaceholdersCount++, Expression.Constant(updated.Value, updated.PropertyType.CanBeNull() ? updated.PropertyType : updated.PropertyType.MakeNullable()));

                if (value.Type != updated.PropertyType)
                {
                    value = Expression.Convert(value, updated.PropertyType);
                }

                assignments.Add(new SqlAssignExpression(new SqlColumnExpression(updated.PropertyType, null, updated.PersistedName), value));
            }

            Expression where = null;

            Debug.Assert(primaryKeys.Length > 0);

            foreach (var primaryKey in primaryKeys)
            {
                var value       = primaryKey.Value;
                var placeholder = (Expression) new SqlConstantPlaceholderExpression(constantPlaceholdersCount++, Expression.Constant(value, primaryKey.PropertyType.CanBeNull() ? primaryKey.PropertyType : primaryKey.PropertyType.MakeNullable()));

                if (placeholder.Type != primaryKey.PropertyType)
                {
                    placeholder = Expression.Convert(placeholder, primaryKey.PropertyType);
                }

                var currentExpression = Expression.Equal(new SqlColumnExpression(primaryKey.PropertyType, null, primaryKey.PersistedName), placeholder);

                where = where == null ? currentExpression : Expression.And(where, currentExpression);
            }

            for (var i = 0; i < assignments.Count; i++)
            {
                valueIndexesToParameterPlaceholderIndexes[i] = i;
            }

            for (var i = 0; i < primaryKeys.Length; i++)
            {
                primaryKeyIndexesToParameterPlaceholderIndexes[i] = i + assignments.Count;
            }

            var expression = (Expression) new SqlUpdateExpression(new SqlTableExpression(typeDescriptor.PersistedName), assignments, where, requiresIdentityInsert);

            expression = SqlObjectOperandComparisonExpander.Expand(expression);

            var result = this.SqlDatabaseContext.SqlQueryFormatterManager.Format(expression, SqlQueryFormatterOptions.Default);

            try
            {
                command             = this.CreateCommand();
                command.CommandText = result.CommandText;

                cachedValue = new SqlCachedUpdateInsertFormatValue {
                    formatResult = result, valueIndexesToParameterPlaceholderIndexes = valueIndexesToParameterPlaceholderIndexes, primaryKeyIndexesToParameterPlaceholderIndexes = primaryKeyIndexesToParameterPlaceholderIndexes
                };

                if (result.Cacheable)
                {
                    this.CacheUpdateCommand(commandKey, cachedValue);
                }

                FillParameters(command, cachedValue, null, null);

                success = true;

                return(command);
            }
            finally
            {
                if (!success)
                {
                    command?.Dispose();
                }
            }
        }
Exemple #6
0
        protected virtual IDbCommand BuildUpdateCommand(TypeDescriptor typeDescriptor, DataAccessObject dataAccessObject)
        {
            IDbCommand      command;
            SqlCommandValue sqlCommandValue;
            var             updatedProperties = dataAccessObject.GetAdvanced().GetChangedPropertiesFlattened();

            if (updatedProperties.Count == 0)
            {
                return(null);
            }

            var primaryKeys = dataAccessObject.GetAdvanced().GetPrimaryKeysForUpdateFlattened();
            var commandKey  = new SqlCommandKey(dataAccessObject.GetType(), updatedProperties);

            if (this.TryGetUpdateCommand(commandKey, out sqlCommandValue))
            {
                command             = this.CreateCommand();
                command.CommandText = sqlCommandValue.commandText;
                this.FillParameters(command, updatedProperties, primaryKeys);

                return(command);
            }

            var assignments = updatedProperties.Select(c => (Expression) new SqlAssignExpression(new SqlColumnExpression(c.PropertyType, null, c.PersistedName), Expression.Constant(c.Value))).ToReadOnlyList();

            Expression where = null;

            var i = 0;

            Debug.Assert(primaryKeys.Length > 0);

            foreach (var primaryKey in primaryKeys)
            {
                var currentExpression = Expression.Equal(new SqlColumnExpression(primaryKey.PropertyType, null, primaryKey.PersistedName), Expression.Constant(primaryKey.Value));

                if (where == null)
                {
                    where = currentExpression;
                }
                else
                {
                    where = Expression.And(where, currentExpression);
                }

                i++;
            }

            var expression = new SqlUpdateExpression(new SqlTableExpression(typeDescriptor.PersistedName), assignments, where);

            expression = (SqlUpdateExpression)SqlObjectOperandComparisonExpander.Expand(expression);

            var result = this.SqlDatabaseContext.SqlQueryFormatterManager.Format(expression, SqlQueryFormatterOptions.Default & ~SqlQueryFormatterOptions.OptimiseOutConstantNulls);

            command = this.CreateCommand();

            command.CommandText = result.CommandText;
            this.CacheUpdateCommand(commandKey, new SqlCommandValue()
            {
                commandText = command.CommandText
            });
            this.FillParameters(command, updatedProperties, primaryKeys);

            return(command);
        }