Skip to content

Commit

Permalink
Refactor ReaderModificationCommandBatch
Browse files Browse the repository at this point in the history
* Allow flexible/alternative parameter strategies
* Insert commands and update SQL immediately

Closes #27583
  • Loading branch information
roji committed Mar 14, 2022
1 parent b560991 commit 3ab3933
Show file tree
Hide file tree
Showing 13 changed files with 382 additions and 406 deletions.
7 changes: 7 additions & 0 deletions src/EFCore.Relational/Storage/IRelationalCommandBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ public interface IRelationalCommandBuilder
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
IRelationalCommandBuilder AddParameter(IRelationalParameter parameter);

/// <summary>
/// Removes the parameter with the given index from this command.
/// </summary>
/// <param name="index">The index of the parameter to be removed.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
IRelationalCommandBuilder RemoveParameterAt(int index);

/// <summary>
/// The source for <see cref="RelationalTypeMapping" />s to use.
/// </summary>
Expand Down
66 changes: 18 additions & 48 deletions src/EFCore.Relational/Storage/RelationalCommandBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,7 @@

namespace Microsoft.EntityFrameworkCore.Storage;

/// <summary>
/// <para>
/// Builds a command to be executed against a relational database.
/// </para>
/// <para>
/// This type is typically used by database providers (and other extensions). It is generally
/// not used in application code.
/// </para>
/// </summary>
/// <remarks>
/// See <see href="https://aka.ms/efcore-docs-providers">Implementation of database providers and extensions</see>
/// for more information and examples.
/// </remarks>
/// <inheritdoc />
public class RelationalCommandBuilder : IRelationalCommandBuilder
{
private readonly List<IRelationalParameter> _parameters = new();
Expand All @@ -42,17 +30,12 @@ public RelationalCommandBuilder(
/// </summary>
protected virtual RelationalCommandBuilderDependencies Dependencies { get; }

/// <summary>
/// The source for <see cref="RelationalTypeMapping" />s to use.
/// </summary>
/// <inheritdoc />
[Obsolete("Code trying to add parameter should add type mapped parameter using TypeMappingSource directly.")]
public virtual IRelationalTypeMappingSource TypeMappingSource
=> Dependencies.TypeMappingSource;

/// <summary>
/// Creates the command.
/// </summary>
/// <returns>The newly created command.</returns>
/// <inheritdoc />
public virtual IRelationalCommand Build()
=> new RelationalCommand(Dependencies, _commandTextBuilder.ToString(), Parameters);

Expand All @@ -62,72 +45,59 @@ public virtual IRelationalCommand Build()
public override string ToString()
=> _commandTextBuilder.ToString();

/// <summary>
/// The collection of parameters.
/// </summary>
/// <inheritdoc />
public virtual IReadOnlyList<IRelationalParameter> Parameters
=> _parameters;

/// <summary>
/// Adds the given parameter to this command.
/// </summary>
/// <param name="parameter">The parameter.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
/// <inheritdoc />
public virtual IRelationalCommandBuilder AddParameter(IRelationalParameter parameter)
{
_parameters.Add(parameter);

return this;
}

/// <summary>
/// Appends an object to the command text.
/// </summary>
/// <param name="value">The object to be written.</param>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
/// <inheritdoc />
public virtual IRelationalCommandBuilder RemoveParameterAt(int index)
{
_parameters.RemoveAt(index);

return this;
}

/// <inheritdoc />
public virtual IRelationalCommandBuilder Append(string value)
{
_commandTextBuilder.Append(value);

return this;
}

/// <summary>
/// Appends a blank line to the command text.
/// </summary>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
/// <inheritdoc />
public virtual IRelationalCommandBuilder AppendLine()
{
_commandTextBuilder.AppendLine();

return this;
}

/// <summary>
/// Increments the indent of subsequent lines.
/// </summary>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
/// <inheritdoc />
public virtual IRelationalCommandBuilder IncrementIndent()
{
_commandTextBuilder.IncrementIndent();

return this;
}

/// <summary>
/// Decrements the indent of subsequent lines.
/// </summary>
/// <returns>The same builder instance so that multiple calls can be chained.</returns>
/// <inheritdoc />
public virtual IRelationalCommandBuilder DecrementIndent()
{
_commandTextBuilder.DecrementIndent();

return this;
}

/// <summary>
/// Gets the length of the command text.
/// </summary>
/// <inheritdoc />
public virtual int CommandTextLength
=> _commandTextBuilder.Length;
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ protected virtual int ConsumeResultSetWithPropagation(int startResultSetIndex, R
}

var tableModification = ModificationCommands[
ResultsPositionalMappingEnabled?[resultSetIndex] == true
ResultsPositionalMappingEnabled?.Length > resultSetIndex && ResultsPositionalMappingEnabled[resultSetIndex]
? startResultSetIndex + reader.DbDataReader.GetInt32(reader.DbDataReader.FieldCount - 1)
: resultSetIndex];

Expand Down Expand Up @@ -231,7 +231,7 @@ protected virtual async Task<int> ConsumeResultSetWithPropagationAsync(
}

var tableModification = ModificationCommands[
ResultsPositionalMappingEnabled?[resultSetIndex] == true
ResultsPositionalMappingEnabled?.Length > resultSetIndex && ResultsPositionalMappingEnabled[resultSetIndex]
? startResultSetIndex + reader.DbDataReader.GetInt32(reader.DbDataReader.FieldCount - 1)
: resultSetIndex];

Expand Down
4 changes: 2 additions & 2 deletions src/EFCore.Relational/Update/Internal/CommandBatchPreparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public CommandBatchPreparer(CommandBatchPreparerDependencies dependencies)
continue;
}

if (!batch.AddCommand(modificationCommand))
if (!batch.TryAddCommand(modificationCommand))
{
if (batch.ModificationCommands.Count == 1
|| batch.ModificationCommands.Count >= _minBatchSize)
Expand Down Expand Up @@ -144,7 +144,7 @@ private ModificationCommandBatch StartNewBatch(
{
parameterNameGenerator.Reset();
var batch = Dependencies.ModificationCommandBatchFactory.Create();
batch.AddCommand(modificationCommand);
batch.TryAddCommand(modificationCommand);
return batch;
}

Expand Down
2 changes: 1 addition & 1 deletion src/EFCore.Relational/Update/ModificationCommandBatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public abstract class ModificationCommandBatch
/// <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);
public abstract bool TryAddCommand(IReadOnlyModificationCommand modificationCommand);

/// <summary>
/// Indicates that no more commands will be added to this batch, and prepares it for execution.
Expand Down
Loading

0 comments on commit 3ab3933

Please sign in to comment.