Skip to content

Commit

Permalink
#1143 Support to RepoDb.SqlServer InsertAll operation.
Browse files Browse the repository at this point in the history
  • Loading branch information
mikependon committed Mar 18, 2023
1 parent 4ee230b commit 02b8edf
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 110 deletions.
3 changes: 3 additions & 0 deletions RepoDb.Core/RepoDb/Extensions/DbConnectionExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2250,12 +2250,15 @@ internal static void SetOutputParameter(QueryField queryField)

#region Order Columns

// TODO: Remove this

/// <summary>
///
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="command"></param>
/// <param name="entities"></param>
[Obsolete("Can be removed during the fixes to #1143.")]
private static void AddOrderColumnParameters<TEntity>(DbCommand command,
IEnumerable<TEntity> entities)
where TEntity : class
Expand Down
33 changes: 14 additions & 19 deletions RepoDb.Core/RepoDb/Operations/DbConnection/InsertAll.cs
Original file line number Diff line number Diff line change
Expand Up @@ -597,18 +597,16 @@ internal static int InsertAllInternalBase<TEntity>(this IDbConnection connection

// Get the results
var position = 0;
do
while (reader.Read())
{
if (reader.Read())
{
var value = Converter.DbNullToNull(reader.GetValue(0));
var index = batchItems.Count > 1 && reader.FieldCount > 1 ? reader.GetInt32(1) : position;
context.KeyPropertySetterFunc.Invoke(batchItems[index], value);
result++;
}
var value = Converter.DbNullToNull(reader.GetValue(0));
var index = batchItems.Count > 1 && reader.FieldCount > 1 ? reader.GetInt32(1) : position;
context.KeyPropertySetterFunc.Invoke(batchItems[index], value);
position++;
}
while (reader.NextResult());

// Set the result
result += batchItems.Count;

// After Execution
Tracer
Expand Down Expand Up @@ -841,19 +839,16 @@ await Tracer

// Get the results
var position = 0;
do
while (await reader.ReadAsync(cancellationToken))
{
if (await reader.ReadAsync(cancellationToken))
{
// No need to use async on this level (await reader.GetFieldValueAsync<object>(0, cancellationToken))
var value = Converter.DbNullToNull(reader.GetValue(0));
var index = batchItems.Count > 1 && reader.FieldCount > 1 ? reader.GetInt32(1) : position;
context.KeyPropertySetterFunc.Invoke(batchItems[index], value);
result++;
}
var value = Converter.DbNullToNull(reader.GetValue(0));
var index = batchItems.Count > 1 && reader.FieldCount > 1 ? reader.GetInt32(1) : position;
context.KeyPropertySetterFunc.Invoke(batchItems[index], value);
position++;
}
while (await reader.NextResultAsync(cancellationToken));

// Set the result
result += batchItems.Count;

// After Execution
await Tracer
Expand Down
30 changes: 19 additions & 11 deletions RepoDb.Core/RepoDb/StatementBuilders/BaseStatementBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -466,25 +466,33 @@ public virtual string CreateInsertAll(string tableName,
// Build the query
builder.Clear();

// Compose
builder.Insert()
.Into()
.TableNameFrom(tableName, DbSetting)
.HintsFrom(hints)
.OpenParen()
.FieldsFrom(insertableFields, DbSetting)
.CloseParen()
.Values();

// Iterate the indexes
for (var index = 0; index < batchSize; index++)
{
builder.Insert()
.Into()
.TableNameFrom(tableName, DbSetting)
.HintsFrom(hints)
.OpenParen()
.FieldsFrom(insertableFields, DbSetting)
.CloseParen()
.Values()
builder
.OpenParen()
.ParametersFrom(insertableFields, index, DbSetting)
.CloseParen()
.End();
.CloseParen();

if (index < batchSize - 1)
{
builder
.WriteText(",");
}
}

// Return the query
return builder.GetString();
return builder.End().GetString();
}

#endregion
Expand Down
77 changes: 21 additions & 56 deletions RepoDb.SqlServer/RepoDb.SqlServer.UnitTests/StatementBuilderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -528,11 +528,9 @@ public void TestSqlServerStatementBuilderCreateInsertAllWithIdentity()
primaryField: null,
identityField: identityField);
var expected = $"" +
$"INSERT INTO [Table] " +
$"( [Field2], [Field3] ) " +
$"VALUES " +
$"( @Field2, @Field3 ) ; " +
$"SELECT CONVERT(INT, SCOPE_IDENTITY()) AS [Result], @__RepoDb_OrderColumn_0 AS [OrderColumn] ;";
$"INSERT INTO [Table] ( [Field2], [Field3] ) " +
$"OUTPUT CONVERT(INT, [INSERTED].[Field1]) AS [Result] " +
$"VALUES ( @Field2, @Field3 ) ;";

// Assert
Assert.AreEqual(expected, actual);
Expand All @@ -554,11 +552,9 @@ public void TestSqlServerStatementBuilderCreateInsertAllWithIdentityAsBigInt()
primaryField: null,
identityField: identityField);
var expected = $"" +
$"INSERT INTO [Table] " +
$"( [Field2], [Field3] ) " +
$"VALUES " +
$"( @Field2, @Field3 ) ; " +
$"SELECT CONVERT(BIGINT, SCOPE_IDENTITY()) AS [Result], @__RepoDb_OrderColumn_0 AS [OrderColumn] ;";
$"INSERT INTO [Table] ( [Field2], [Field3] ) " +
$"OUTPUT CONVERT(BIGINT, [INSERTED].[Field1]) AS [Result] " +
$"VALUES ( @Field2, @Field3 ) ;";

// Assert
Assert.AreEqual(expected, actual);
Expand All @@ -571,7 +567,6 @@ public void TestSqlServerStatementBuilderCreateInsertAllWithPrimaryAndIdentity()
var statementBuilder = StatementBuilderMapper.Get<SqlConnection>();
var tableName = "Table";
var fields = Field.From(new[] { "Field1", "Field2", "Field3" });
var primaryField = new DbField("Field1", true, false, false, typeof(int), null, null, null, null);
var identityField = new DbField("Field2", false, true, false, typeof(int), null, null, null, null);

// Act
Expand All @@ -581,11 +576,9 @@ public void TestSqlServerStatementBuilderCreateInsertAllWithPrimaryAndIdentity()
primaryField: null,
identityField: identityField);
var expected = $"" +
$"INSERT INTO [Table] " +
$"( [Field1], [Field3] ) " +
$"VALUES " +
$"( @Field1, @Field3 ) ; " +
$"SELECT CONVERT(INT, SCOPE_IDENTITY()) AS [Result], @__RepoDb_OrderColumn_0 AS [OrderColumn] ;";
$"INSERT INTO [Table] ( [Field1], [Field3] ) " +
$"OUTPUT CONVERT(INT, [INSERTED].[Field2]) AS [Result] " +
$"VALUES ( @Field1, @Field3 ) ;";

// Assert
Assert.AreEqual(expected, actual);
Expand All @@ -608,11 +601,9 @@ public void TestSqlServerStatementBuilderCreateInsertAllWithPrimaryAndIdentityAs
primaryField: null,
identityField: identityField);
var expected = $"" +
$"INSERT INTO [Table] " +
$"( [Field1], [Field3] ) " +
$"VALUES " +
$"( @Field1, @Field3 ) ; " +
$"SELECT CONVERT(BIGINT, SCOPE_IDENTITY()) AS [Result], @__RepoDb_OrderColumn_0 AS [OrderColumn] ;";
$"INSERT INTO [Table] ( [Field1], [Field3] ) " +
$"OUTPUT CONVERT(BIGINT, [INSERTED].[Field2]) AS [Result] " +
$"VALUES ( @Field1, @Field3 ) ;";

// Assert
Assert.AreEqual(expected, actual);
Expand All @@ -634,21 +625,9 @@ public void TestSqlServerStatementBuilderCreateInsertAllWithIdentityForThreeBatc
primaryField: null,
identityField: identityField);
var expected = $"" +
$"INSERT INTO [Table] " +
$"( [Field2], [Field3] ) " +
$"VALUES " +
$"( @Field2, @Field3 ) ; " +
$"SELECT CONVERT(INT, SCOPE_IDENTITY()) AS [Result], @__RepoDb_OrderColumn_0 AS [OrderColumn] ; " +
$"INSERT INTO [Table] " +
$"( [Field2], [Field3] ) " +
$"VALUES " +
$"( @Field2_1, @Field3_1 ) ; " +
$"SELECT CONVERT(INT, SCOPE_IDENTITY()) AS [Result], @__RepoDb_OrderColumn_1 AS [OrderColumn] ; " +
$"INSERT INTO [Table] " +
$"( [Field2], [Field3] ) " +
$"VALUES " +
$"( @Field2_2, @Field3_2 ) ; " +
$"SELECT CONVERT(INT, SCOPE_IDENTITY()) AS [Result], @__RepoDb_OrderColumn_2 AS [OrderColumn] ;";
$"INSERT INTO [Table] ( [Field2], [Field3] ) " +
$"OUTPUT CONVERT(INT, [INSERTED].[Field1]) AS [Result] " +
$"VALUES ( @Field2, @Field3 ) , ( @Field2_1, @Field3_1 ) , ( @Field2_2, @Field3_2 ) ;";

// Assert
Assert.AreEqual(expected, actual);
Expand All @@ -671,11 +650,9 @@ public void TestSqlServerStatementBuilderCreateInsertAllWithIdentityWithHints()
identityField: identityField,
hints: SqlServerTableHints.TabLock);
var expected = $"" +
$"INSERT INTO [Table] WITH (TABLOCK) " +
$"( [Field2], [Field3] ) " +
$"VALUES " +
$"( @Field2, @Field3 ) ; " +
$"SELECT CONVERT(INT, SCOPE_IDENTITY()) AS [Result], @__RepoDb_OrderColumn_0 AS [OrderColumn] ;";
$"INSERT INTO [Table] WITH (TABLOCK) ( [Field2], [Field3] ) " +
$"OUTPUT CONVERT(INT, [INSERTED].[Field1]) AS [Result] " +
$"VALUES ( @Field2, @Field3 ) ;";

// Assert
Assert.AreEqual(expected, actual);
Expand All @@ -698,21 +675,9 @@ public void TestSqlServerStatementBuilderCreateInsertAllWithIdentityForThreeBatc
identityField: identityField,
hints: SqlServerTableHints.TabLock);
var expected = $"" +
$"INSERT INTO [Table] WITH (TABLOCK) " +
$"( [Field2], [Field3] ) " +
$"VALUES " +
$"( @Field2, @Field3 ) ; " +
$"SELECT CONVERT(INT, SCOPE_IDENTITY()) AS [Result], @__RepoDb_OrderColumn_0 AS [OrderColumn] ; " +
$"INSERT INTO [Table] WITH (TABLOCK) " +
$"( [Field2], [Field3] ) " +
$"VALUES " +
$"( @Field2_1, @Field3_1 ) ; " +
$"SELECT CONVERT(INT, SCOPE_IDENTITY()) AS [Result], @__RepoDb_OrderColumn_1 AS [OrderColumn] ; " +
$"INSERT INTO [Table] WITH (TABLOCK) " +
$"( [Field2], [Field3] ) " +
$"VALUES " +
$"( @Field2_2, @Field3_2 ) ; " +
$"SELECT CONVERT(INT, SCOPE_IDENTITY()) AS [Result], @__RepoDb_OrderColumn_2 AS [OrderColumn] ;";
$"INSERT INTO [Table] WITH (TABLOCK) ( [Field2], [Field3] ) " +
$"OUTPUT CONVERT(INT, [INSERTED].[Field1]) AS [Result] " +
$"VALUES ( @Field2, @Field3 ) , ( @Field2_1, @Field3_1 ) , ( @Field2_2, @Field3_2 ) ;";

// Assert
Assert.AreEqual(expected, actual);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,30 +280,14 @@ public override string CreateInsertAll(string tableName,
if (keyColumn != null)
{
var dbType = new ClientTypeToDbTypeResolver().Resolve(keyColumn.Type);
string databaseType = null;

if (dbType != null)
{
databaseType = new DbTypeToSqlServerStringNameResolver().Resolve(dbType.Value);
}

var commandTexts = new List<string>();
var splitted = commandText.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

for (var index = 0; index < splitted.Length; index++)
{
var line = splitted[index].Trim();
var keyColumnText = (keyColumn == identityField || string.Equals(keyColumn.Name, identityField?.Name, StringComparison.OrdinalIgnoreCase)) ? "SCOPE_IDENTITY()" :
keyColumn.Name.AsParameter(index, DbSetting);
var returnValue = keyColumn != null ?
string.IsNullOrWhiteSpace(databaseType) ?
keyColumnText : string.Concat("CONVERT(", databaseType, ", ", keyColumnText, ")") : "NULL";
var result = string.Concat("SELECT ", returnValue, $" AS [Result]," +
$" {DbSetting.ParameterPrefix}__RepoDb_OrderColumn_{index} AS [OrderColumn] ;");
commandTexts.Add(string.Concat(line, " ; ", result));
}

commandText = commandTexts.Join(" ");
var databaseType = (dbType != null) ? new DbTypeToSqlServerStringNameResolver().Resolve(dbType.Value) : null;
var returnValue = keyColumn == null ? "NULL" :
string.IsNullOrWhiteSpace(databaseType) ?
string.Concat("[INSERTED].", keyColumn.Name.AsQuoted(DbSetting)) :
string.Concat("CONVERT(", databaseType, ", [INSERTED].", keyColumn.Name.AsQuoted(DbSetting), ")");
var result = string.Concat("OUTPUT ", returnValue, $" AS [Result] ");
//$", {DbSetting.ParameterPrefix}__RepoDb_OrderColumn_{0} AS [OrderColumn] ");
commandText = commandText.Insert(commandText.IndexOf("VALUES"), result);
}

// Return the query
Expand Down

0 comments on commit 02b8edf

Please sign in to comment.