/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public override ResultSetMapping AppendDeleteOperation( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition, out bool requiresTransaction) { // We normally do a simple DELETE, with an OUTPUT clause emitting "1" for concurrency checking. // However, if there are triggers defined, OUTPUT (without INTO) is not supported, so we do UPDATE+SELECT. if (!HasAnyTriggers(command)) { return(base.AppendDeleteOperation(commandStringBuilder, command, commandPosition, out requiresTransaction)); } var name = command.TableName; var schema = command.Schema; var operations = command.ColumnModifications; var conditionOperations = operations.Where(o => o.IsCondition).ToList(); requiresTransaction = false; AppendDeleteCommand(commandStringBuilder, name, schema, Array.Empty <IColumnModification>(), conditionOperations); return(AppendSelectAffectedCountCommand(commandStringBuilder, name, schema, commandPosition)); }
private void Format(IReadOnlyModificationCommand command, StringBuilder builder) { var entry = command.Entries.First(); var entityType = entry.EntityType; builder.Append(entityType.DisplayName()); if (_sensitiveLoggingEnabled) { builder.Append(" { "); var properties = entityType.FindPrimaryKey() !.Properties; for (var i = 0; i < properties.Count; i++) { var keyProperty = properties[i]; builder.Append('\''); builder.Append(keyProperty.Name); builder.Append("': "); builder.Append(entry.GetCurrentValue(keyProperty)); if (i != properties.Count - 1) { builder.Append(", "); } } builder.Append(" } "); } else { builder.Append(' '); } builder.Append('['); builder.Append(entry.EntityState); builder.Append(']'); }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public override ResultSetMapping AppendInsertOperation( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition, out bool requiresTransaction) { // If no database-generated columns need to be read back, just do a simple INSERT (default behavior). // If there are generated columns but there are no triggers defined on the table, we can do a simple INSERT ... OUTPUT // (without INTO), which is also the default behavior, doesn't require a transaction and is the most efficient. if (command.ColumnModifications.All(o => !o.IsRead) || !HasAnyTriggers(command)) { return(base.AppendInsertOperation(commandStringBuilder, command, commandPosition, out requiresTransaction)); } // SQL Server doesn't allow INSERT ... OUTPUT on tables with triggers. // If the only generated column is an IDENTITY, do INSERT+SELECT which is relatively fast. // Otherwise fall back to INSERT ... OUTPUT INTO @inserted; SELECT ... FROM @inserted. var table = StoreObjectIdentifier.Table(command.TableName, command.Schema); return(command.ColumnModifications.All( o => !o.IsKey || !o.IsRead || o.Property?.GetValueGenerationStrategy(table) == SqlServerValueGenerationStrategy.IdentityColumn) ? AppendInsertAndSelectOperations(commandStringBuilder, command, commandPosition, out requiresTransaction) : AppendInsertSingleRowWithOutputInto( commandStringBuilder, command, command.ColumnModifications.Where(o => o.IsKey).ToList(), command.ColumnModifications.Where(o => o.IsRead).ToList(), commandPosition, out requiresTransaction)); }
public override ResultSetMapping AppendUpdateOperation( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition) { Check.NotNull(commandStringBuilder, nameof(commandStringBuilder)); Check.NotNull(command, nameof(command)); var tableName = command.TableName; var schemaName = command.Schema; var operations = command.ColumnModifications; var writeOperations = operations.Where(o => o.IsWrite).ToArray(); var conditionOperations = operations.Where(o => o.IsCondition).ToArray(); var readOperations = operations.Where(o => o.IsRead).ToArray(); AppendUpdateCommandHeader(commandStringBuilder, tableName, schemaName, writeOperations); AppendWhereClause(commandStringBuilder, conditionOperations); if (readOperations.Length > 0) { AppendReturningClause(commandStringBuilder, readOperations); } commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); return(ResultSetMapping.NoResultSet); }
public virtual ResultSetMapping AppendInsertOperation( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition, bool overridingSystemValue) { Check.NotNull(commandStringBuilder, nameof(commandStringBuilder)); Check.NotNull(command, nameof(command)); var name = command.TableName; var schema = command.Schema; var operations = command.ColumnModifications; var writeOperations = operations.Where(o => o.IsWrite).ToArray(); var readOperations = operations.Where(o => o.IsRead).ToArray(); AppendInsertCommandHeader(commandStringBuilder, command.TableName, command.Schema, writeOperations); if (overridingSystemValue) { commandStringBuilder.AppendLine().Append("OVERRIDING SYSTEM VALUE"); } AppendValuesHeader(commandStringBuilder, writeOperations); AppendValues(commandStringBuilder, name, schema, writeOperations); if (readOperations.Length > 0) { AppendReturningClause(commandStringBuilder, readOperations); } commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); return(ResultSetMapping.NoResultSet); }
/// <summary> /// Appends a SQL command for updating a row to the commands being built. /// </summary> /// <param name="commandStringBuilder"> The builder to which the SQL should be appended. </param> /// <param name="command"> The command that represents the delete operation. </param> /// <param name="commandPosition"> The ordinal of this command in the batch. </param> /// <returns> The <see cref="ResultSetMapping" /> for the command. </returns> public virtual ResultSetMapping AppendUpdateOperation( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition) { Check.NotNull(commandStringBuilder, nameof(commandStringBuilder)); Check.NotNull(command, nameof(command)); var name = command.TableName; var schema = command.Schema; var operations = command.ColumnModifications; var writeOperations = operations.Where(o => o.IsWrite).ToList(); var conditionOperations = operations.Where(o => o.IsCondition).ToList(); var readOperations = operations.Where(o => o.IsRead).ToList(); AppendUpdateCommand(commandStringBuilder, name, schema, writeOperations, conditionOperations); if (readOperations.Count > 0) { var keyOperations = operations.Where(o => o.IsKey).ToList(); return(AppendSelectAffectedCommand(commandStringBuilder, name, schema, readOperations, keyOperations, commandPosition)); } return(AppendSelectAffectedCountCommand(commandStringBuilder, name, schema, commandPosition)); }
public override ResultSetMapping AppendDeleteOperation( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition) { AppendDeleteOperationCalls++; return(base.AppendDeleteOperation(commandStringBuilder, command, commandPosition)); }
public override ResultSetMapping AppendUpdateOperation( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition, out bool requiresTransaction) { AppendUpdateOperationCalls++; return(base.AppendUpdateOperation(commandStringBuilder, command, commandPosition, out requiresTransaction)); }
private ModificationCommandBatch StartNewBatch( ParameterNameGenerator parameterNameGenerator, IReadOnlyModificationCommand modificationCommand) { parameterNameGenerator.Reset(); var batch = Dependencies.ModificationCommandBatchFactory.Create(); batch.AddCommand(modificationCommand); return(batch); }
/// <summary> /// Appends a SQL command for deleting a row to the commands being built. /// </summary> /// <param name="commandStringBuilder">The builder to which the SQL should be appended.</param> /// <param name="command">The command that represents the delete operation.</param> /// <param name="commandPosition">The ordinal of this command in the batch.</param> /// <returns>The <see cref="ResultSetMapping" /> for the command.</returns> public virtual ResultSetMapping AppendDeleteOperation( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition) { var name = command.TableName; var schema = command.Schema; var conditionOperations = command.ColumnModifications.Where(o => o.IsCondition).ToList(); AppendDeleteCommand(commandStringBuilder, name, schema, conditionOperations); return(AppendSelectAffectedCountCommand(commandStringBuilder, name, schema, commandPosition)); }
protected override bool CanAddCommand(IReadOnlyModificationCommand modificationCommand) { if (ModificationCommands.Count >= _maxBatchSize) { return(false); } var newParamCount = (long)_parameterCount + modificationCommand.ColumnModifications.Count; if (newParamCount > int.MaxValue) { return(false); } _parameterCount = (int)newParamCount; return(true); }
/// <summary> /// Appends a SQL command for deleting a row to the commands being built. /// </summary> /// <param name="commandStringBuilder">The builder to which the SQL should be appended.</param> /// <param name="command">The command that represents the delete operation.</param> /// <param name="commandPosition">The ordinal of this command in the batch.</param> /// <param name="requiresTransaction">Returns whether the SQL appended must be executed in a transaction to work correctly.</param> /// <returns>The <see cref="ResultSetMapping" /> for the command.</returns> public virtual ResultSetMapping AppendDeleteOperation( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition, out bool requiresTransaction) { var name = command.TableName; var schema = command.Schema; var conditionOperations = command.ColumnModifications.Where(o => o.IsCondition).ToList(); requiresTransaction = false; AppendDeleteCommand( commandStringBuilder, name, schema, Array.Empty <IColumnModification>(), conditionOperations, additionalReadValues: "1"); return(ResultSetMapping.LastInResultSet); }
public override bool AddCommand(IReadOnlyModificationCommand modificationCommand) { if (_sqlServerBulkConfiguration.Disabled) { _bulkMode = false; return(_modificationCommandBatch.AddCommand(modificationCommand)); } var state = modificationCommand.EntityState; var bulkMode = false; if ((state == EntityState.Added && _bulkOptions.InsertEnabled) || (state == EntityState.Deleted && _bulkOptions.DeleteEnabled)) { bulkMode = true; } if (!_state.HasValue) { _state = state; _table = modificationCommand.TableName; _schema = modificationCommand.Schema; _bulkMode = bulkMode; } if (bulkMode != _bulkMode) { return(false); } if (!_bulkMode) { return(_modificationCommandBatch.AddCommand(modificationCommand)); } if (_state != modificationCommand.EntityState || _table != modificationCommand.TableName || _schema != modificationCommand.Schema) { return(false); } _commands = _commands.Add(modificationCommand); return(true); }
public override ResultSetMapping AppendDeleteOperation( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition, out bool requiresTransaction) { // The default implementation adds RETURNING 1 to do concurrency check (was the row actually deleted), but in PostgreSQL we check // the per-statement row-affected value exposed by Npgsql in the batch; so no need for RETURNING 1. var name = command.TableName; var schema = command.Schema; var conditionOperations = command.ColumnModifications.Where(o => o.IsCondition).ToList(); requiresTransaction = false; AppendDeleteCommand(commandStringBuilder, name, schema, Array.Empty <IColumnModification>(), conditionOperations); return(ResultSetMapping.NoResultSet); }
private void Format(IIndex index, IReadOnlyModificationCommand source, IReadOnlyModificationCommand target, StringBuilder builder) { var reverseDependency = source.EntityState != EntityState.Deleted; if (reverseDependency) { builder.AppendLine(" <-"); } else { builder.Append(' '); } builder.Append("Index "); var dependentCommand = reverseDependency ? target : source; var dependentEntry = dependentCommand.Entries.First(e => index.DeclaringEntityType.IsAssignableFrom(e.EntityType)); builder.Append("{ "); for (var i = 0; i < index.Properties.Count; i++) { var property = index.Properties[i]; builder.Append('\''); builder.Append(property.Name); builder.Append('\''); if (_sensitiveLoggingEnabled) { builder.Append(": "); builder.Append(dependentEntry.GetCurrentValue(property)); } if (i != index.Properties.Count - 1) { builder.Append(", "); } } builder.Append(" } "); if (!reverseDependency) { builder.AppendLine("<-"); } }
/// <summary> /// Appends a SQL command for inserting a row to the commands being built. /// </summary> /// <param name="commandStringBuilder">The builder to which the SQL should be appended.</param> /// <param name="command">The command that represents the delete operation.</param> /// <param name="commandPosition">The ordinal of this command in the batch.</param> /// <param name="requiresTransaction">Returns whether the SQL appended must be executed in a transaction to work correctly.</param> /// <returns>The <see cref="ResultSetMapping" /> for the command.</returns> public virtual ResultSetMapping AppendInsertOperation( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition, out bool requiresTransaction) { var name = command.TableName; var schema = command.Schema; var operations = command.ColumnModifications; var writeOperations = operations.Where(o => o.IsWrite).ToList(); var readOperations = operations.Where(o => o.IsRead).ToList(); AppendInsertCommand(commandStringBuilder, name, schema, writeOperations, readOperations); requiresTransaction = false; return(readOperations.Count > 0 ? ResultSetMapping.LastInResultSet : ResultSetMapping.NoResultSet); }
private static void AddMatchingPredecessorEdge <T>( Dictionary <T, List <IReadOnlyModificationCommand> > predecessorsMap, T keyValue, Multigraph <IReadOnlyModificationCommand, IAnnotatable> commandGraph, IReadOnlyModificationCommand command, IAnnotatable edge) where T : notnull { if (predecessorsMap.TryGetValue(keyValue, out var predecessorCommands)) { foreach (var predecessor in predecessorCommands) { if (predecessor != command) { commandGraph.AddEdge(predecessor, command, edge); } } } }
/// <summary> /// Appends a SQL command for updating a row to the commands being built. /// </summary> /// <param name="commandStringBuilder">The builder to which the SQL should be appended.</param> /// <param name="command">The command that represents the delete operation.</param> /// <param name="commandPosition">The ordinal of this command in the batch.</param> /// <param name="requiresTransaction">Returns whether the SQL appended must be executed in a transaction to work correctly.</param> /// <returns>The <see cref="ResultSetMapping" /> for the command.</returns> public virtual ResultSetMapping AppendUpdateOperation( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition, out bool requiresTransaction) { var name = command.TableName; var schema = command.Schema; var operations = command.ColumnModifications; var writeOperations = operations.Where(o => o.IsWrite).ToList(); var conditionOperations = operations.Where(o => o.IsCondition).ToList(); var readOperations = operations.Where(o => o.IsRead).ToList(); requiresTransaction = false; AppendUpdateCommand( commandStringBuilder, name, schema, writeOperations, readOperations, conditionOperations, additionalReadValues: readOperations.Count == 0 ? "1" : null); return(ResultSetMapping.LastInResultSet); }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> protected virtual ResultSetMapping AppendInsertAndSelectOperations( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition, out bool requiresTransaction) { var name = command.TableName; var schema = command.Schema; var operations = command.ColumnModifications; var writeOperations = operations.Where(o => o.IsWrite).ToList(); var readOperations = operations.Where(o => o.IsRead).ToList(); var keyOperations = operations.Where(o => o.IsKey).ToList(); Check.DebugAssert(readOperations.Count > 0, "AppendInsertAndSelectOperations called without any read operations"); requiresTransaction = true; AppendInsertCommand(commandStringBuilder, name, schema, writeOperations, readOperations: Array.Empty <IColumnModification>()); return(AppendSelectAffectedCommand(commandStringBuilder, name, schema, readOperations, keyOperations, commandPosition)); }
/// <summary> /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// </summary> public override ResultSetMapping AppendUpdateOperation( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition, out bool requiresTransaction) { // We normally do a simple UPDATE with an OUTPUT clause (either for the generated columns, or for "1" for concurrency checking). // However, if there are triggers defined, OUTPUT (without INTO) is not supported, so we do UPDATE+SELECT. if (!HasAnyTriggers(command)) { return(base.AppendUpdateOperation(commandStringBuilder, command, commandPosition, out requiresTransaction)); } var name = command.TableName; var schema = command.Schema; var operations = command.ColumnModifications; var writeOperations = operations.Where(o => o.IsWrite).ToList(); var conditionOperations = operations.Where(o => o.IsCondition).ToList(); var readOperations = operations.Where(o => o.IsRead).ToList(); AppendUpdateCommand(commandStringBuilder, name, schema, writeOperations, Array.Empty <IColumnModification>(), conditionOperations); if (readOperations.Count > 0) { var keyOperations = operations.Where(o => o.IsKey).ToList(); requiresTransaction = true; return(AppendSelectAffectedCommand(commandStringBuilder, name, schema, readOperations, keyOperations, commandPosition)); } requiresTransaction = false; return(AppendSelectAffectedCountCommand(commandStringBuilder, name, schema, commandPosition)); }
public override ResultSetMapping AppendUpdateOperation(StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition) { var name = command.TableName; var operations = command.ColumnModifications; var writeOperations = operations.Where(o => o.IsWrite).ToList(); var readOperations = operations.Where(o => o.IsRead).ToList(); var conditionOperations = operations.Where(o => o.IsCondition).ToList(); var inputOperations = GenerateParameters(operations.Where(o => o.IsWrite || o.IsCondition)).ToList(); var anyRead = readOperations.Any(); commandStringBuilder.Append("EXECUTE BLOCK ("); commandStringBuilder.AppendJoin(inputOperations, (b, p) => { b.Append(p.name); b.Append(" "); b.Append(p.type); b.Append(" = ?"); }, ", "); commandStringBuilder.AppendLine(")"); commandStringBuilder.Append("RETURNS ("); if (anyRead) { commandStringBuilder.AppendJoin(readOperations, (b, e) => { var type = GetColumnType(e); b.Append(SqlGenerationHelper.DelimitIdentifier(e.ColumnName)); b.Append(" "); b.Append(type); }, ", "); } else { commandStringBuilder.Append("ROWS_AFFECTED INT"); } commandStringBuilder.AppendLine(")"); commandStringBuilder.AppendLine("AS"); commandStringBuilder.AppendLine("BEGIN"); AppendUpdateCommandHeader(commandStringBuilder, name, null, writeOperations); AppendWhereClause(commandStringBuilder, conditionOperations); if (anyRead) { commandStringBuilder.AppendLine(); commandStringBuilder.Append("RETURNING "); commandStringBuilder.AppendJoin(readOperations, (b, e) => { b.Append(SqlGenerationHelper.DelimitIdentifier(e.ColumnName)); }, ", "); commandStringBuilder.Append(" INTO "); commandStringBuilder.AppendJoin(readOperations, (b, e) => { b.Append(":"); b.Append(SqlGenerationHelper.DelimitIdentifier(e.ColumnName)); }, ", "); } commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); if (!anyRead) { commandStringBuilder.AppendLine("ROWS_AFFECTED = ROW_COUNT;"); commandStringBuilder.AppendLine("SUSPEND;"); } else { commandStringBuilder.AppendLine("IF (ROW_COUNT > 0) THEN"); commandStringBuilder.AppendLine("SUSPEND;"); } commandStringBuilder.Append("END"); commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); return(ResultSetMapping.LastInResultSet); }
protected override bool CanAddCommand(IReadOnlyModificationCommand modificationCommand) => ModificationCommands.Count < _maxBatchSize;
/// <summary> /// Adds the given insert/update/delete <see cref="ModificationCommands" /> to the batch. /// </summary> /// <param name="modificationCommand">The command to add.</param> /// <returns> /// <see langword="true" /> if the command was successfully added; <see langword="false" /> if there was no /// room in the current batch to add the command and it must instead be added to a new batch. /// </returns> public abstract bool AddCommand(IReadOnlyModificationCommand modificationCommand);
/// <summary> /// Only returns <see langword="true" /> if the no command has already been added. /// </summary> /// <param name="modificationCommand">The command to potentially add.</param> /// <returns><see langword="true" /> if no command has already been added.</returns> protected override bool CanAddCommand(IReadOnlyModificationCommand modificationCommand) => ModificationCommands.Count == 0;
private void Format(IForeignKey foreignKey, IReadOnlyModificationCommand source, IReadOnlyModificationCommand target, StringBuilder builder) { var reverseDependency = !source.Entries.Any(e => foreignKey.DeclaringEntityType.IsAssignableFrom(e.EntityType)); if (reverseDependency) { builder.AppendLine(" <-"); } else { builder.Append(' '); } if (foreignKey.DependentToPrincipal != null || foreignKey.PrincipalToDependent != null) { if (!reverseDependency && foreignKey.DependentToPrincipal != null) { builder.Append(foreignKey.DependentToPrincipal.Name); builder.Append(' '); } if (foreignKey.PrincipalToDependent != null) { builder.Append(foreignKey.PrincipalToDependent.Name); builder.Append(' '); } if (reverseDependency && foreignKey.DependentToPrincipal != null) { builder.Append(foreignKey.DependentToPrincipal.Name); builder.Append(' '); } } else { builder.Append("ForeignKey "); } var dependentCommand = reverseDependency ? target : source; var dependentEntry = dependentCommand.Entries.First(e => foreignKey.DeclaringEntityType.IsAssignableFrom(e.EntityType)); builder.Append("{ "); for (var i = 0; i < foreignKey.Properties.Count; i++) { var property = foreignKey.Properties[i]; builder.Append('\''); builder.Append(property.Name); builder.Append('\''); if (_sensitiveLoggingEnabled) { builder.Append(": "); builder.Append(dependentEntry.GetCurrentValue(property)); } if (i != foreignKey.Properties.Count - 1) { builder.Append(", "); } } builder.Append(" } "); if (!reverseDependency) { builder.AppendLine("<-"); } }
public override ResultSetMapping AppendInsertOperation( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition) => AppendInsertOperation(commandStringBuilder, command, commandPosition, false);
public override ResultSetMapping AppendInsertOperation( StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition, out bool requiresTransaction) => AppendInsertOperation(commandStringBuilder, command, commandPosition, overridingSystemValue: false, out requiresTransaction);
public override ResultSetMapping AppendInsertOperation(StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition) { var result = ResultSetMapping.NoResultSet; var name = command.TableName; var operations = command.ColumnModifications; var writeOperations = operations.Where(o => o.IsWrite).ToList(); var readOperations = operations.Where(o => o.IsRead).ToList(); var anyRead = readOperations.Any(); AppendInsertCommandHeader(commandStringBuilder, name, null, writeOperations); AppendValuesHeader(commandStringBuilder, writeOperations); AppendValues(commandStringBuilder, name, null, writeOperations); if (anyRead) { commandStringBuilder.AppendLine(); commandStringBuilder.Append("RETURNING "); commandStringBuilder.AppendJoin(readOperations, (b, e) => { b.Append(SqlGenerationHelper.DelimitIdentifier(e.ColumnName)); }, ", "); result = ResultSetMapping.LastInResultSet; } commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); return(result); }
public override ResultSetMapping AppendDeleteOperation(StringBuilder commandStringBuilder, IReadOnlyModificationCommand command, int commandPosition) { var name = command.TableName; var operations = command.ColumnModifications; var conditionOperations = operations.Where(o => o.IsCondition).ToList(); var inputOperations = GenerateParameters(conditionOperations); commandStringBuilder.Append("EXECUTE BLOCK ("); commandStringBuilder.AppendJoin(inputOperations, (b, p) => { b.Append(p.name); b.Append(" "); b.Append(p.type); b.Append(" = ?"); }, ", "); commandStringBuilder.AppendLine(")"); commandStringBuilder.AppendLine("RETURNS (ROWS_AFFECTED INT)"); commandStringBuilder.AppendLine("AS"); commandStringBuilder.AppendLine("BEGIN"); AppendDeleteCommandHeader(commandStringBuilder, name, null); AppendWhereClause(commandStringBuilder, conditionOperations); commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); commandStringBuilder.AppendLine(); commandStringBuilder.AppendLine("ROWS_AFFECTED = ROW_COUNT;"); commandStringBuilder.AppendLine("SUSPEND;"); commandStringBuilder.Append("END"); commandStringBuilder.Append(SqlGenerationHelper.StatementTerminator).AppendLine(); return(ResultSetMapping.LastInResultSet); }
protected override bool CanAddCommand(IReadOnlyModificationCommand modificationCommand) => ShouldAddCommand;