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); }
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); } }
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); }
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(); } } }
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); }