Skip to content

Commit adb91c9

Browse files
author
Jason Valdez
committed
Added test to allow for direct BulkCopy with no batching
1 parent 49fb2e9 commit adb91c9

File tree

7 files changed

+142
-38
lines changed

7 files changed

+142
-38
lines changed

src/IntegrationTests/BulkLoading/BulkLoaderForBatchSizeTests.cs

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
using System.Collections.Generic;
2-
using System.Data.SqlClient;
3-
using System.Linq;
1+
using System.Linq;
42
using FluentAssertions;
53
using ivaldez.Sql.IntegrationTests.Data;
64
using ivaldez.Sql.SqlBulkLoader;
@@ -10,28 +8,6 @@ namespace ivaldez.Sql.IntegrationTests.BulkLoading
108
{
119
public class BulkLoaderForBatchSizeTests
1210
{
13-
public class SqlBulkCopyUtilitySpy: BulkLoader.ISqlBulkCopyUtility
14-
{
15-
public void BulkCopy<T>(string tableName,
16-
SqlConnection conn,
17-
SqlBulkCopyOptions options,
18-
BulkLoader.TargetProperty[] targetProperties,
19-
IEnumerable<T> toInsert)
20-
{
21-
BulkCopyCalled++;
22-
23-
new BulkLoader.SqlBulkCopyUtility()
24-
.BulkCopy(tableName,
25-
conn,
26-
options,
27-
targetProperties,
28-
toInsert);
29-
}
30-
31-
public int BulkCopyCalled { get; set; }
32-
}
33-
34-
3511
[Fact]
3612
public void ShouldBatchBulkCopyCommandsByOptionValue()
3713
{
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using System.Collections.Generic;
2+
using System.Data.SqlClient;
3+
using System.Linq;
4+
using FluentAssertions;
5+
using ivaldez.Sql.IntegrationTests.Data;
6+
using ivaldez.Sql.SqlBulkLoader;
7+
using Xunit;
8+
9+
namespace ivaldez.Sql.IntegrationTests.BulkLoading
10+
{
11+
public class BulkLoaderForNoBatchTests
12+
{
13+
[Fact]
14+
public void ShouldNotBatchWhenOptionSelected()
15+
{
16+
var testingDatabaseService = new TestingDatabaseService();
17+
testingDatabaseService.CreateTestDatabase();
18+
19+
var dataGateway = new TestingDataGateway(testingDatabaseService);
20+
21+
dataGateway.DropTable();
22+
dataGateway.CreateSingleSurrogateKeyTable();
23+
24+
var dtos = new[]
25+
{
26+
new SampleSurrogateKey
27+
{
28+
Pk = 100,
29+
TextValue = "JJ",
30+
IntValue = 100,
31+
DecimalValue = 100.99m
32+
},
33+
new SampleSurrogateKey
34+
{
35+
Pk = 200,
36+
TextValue = "ZZ",
37+
IntValue = 999,
38+
DecimalValue = 123.45m
39+
}
40+
};
41+
42+
var sqlBulkCopyUtilitySpy = new SqlBulkCopyUtilitySpy();
43+
44+
dataGateway.ExecuteWithConnection(conn =>
45+
{
46+
new BulkLoader(sqlBulkCopyUtilitySpy)
47+
.InsertWithOptions("Sample", conn, true, dtos)
48+
.SetBatchSize(1)
49+
.NoBatch()
50+
.Execute();
51+
});
52+
53+
sqlBulkCopyUtilitySpy.BulkCopyCalled.Should().Be(1);
54+
55+
var databaseDtos = dataGateway.GetAllSampleSurrogateKey().ToArray();
56+
57+
var firstDto = databaseDtos.First(x => x.TextValue == "JJ");
58+
firstDto.IntValue.Should().Be(100);
59+
firstDto.DecimalValue.Should().Be(100.99m);
60+
61+
var secondDto = databaseDtos.First(x => x.TextValue == "ZZ");
62+
secondDto.IntValue.Should().Be(999);
63+
secondDto.DecimalValue.Should().Be(123.45m);
64+
}
65+
}
66+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Collections.Generic;
2+
using System.Data.SqlClient;
3+
using ivaldez.Sql.SqlBulkLoader;
4+
5+
namespace ivaldez.Sql.IntegrationTests.BulkLoading
6+
{
7+
public class SqlBulkCopyUtilitySpy: BulkLoader.ISqlBulkCopyUtility
8+
{
9+
public void BulkCopy<T>(string tableName,
10+
SqlConnection conn,
11+
SqlBulkCopyOptions options,
12+
BulkLoader.TargetProperty[] targetProperties,
13+
IEnumerable<T> toInsert)
14+
{
15+
BulkCopyCalled++;
16+
17+
new BulkLoader.SqlBulkCopyUtility()
18+
.BulkCopy(tableName,
19+
conn,
20+
options,
21+
targetProperties,
22+
toInsert);
23+
}
24+
25+
public int BulkCopyCalled { get; set; }
26+
}
27+
}

src/IntegrationTests/IntegrationTests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,12 @@
6868
</Reference>
6969
</ItemGroup>
7070
<ItemGroup>
71+
<Compile Include="BulkLoading\BulkLoaderForNoBatchTests.cs" />
7172
<Compile Include="BulkLoading\BulkLoaderForBatchSizeTests.cs" />
7273
<Compile Include="BulkLoading\BulkLoaderForFieldOptionsTests.cs" />
7374
<Compile Include="BulkLoading\BulkLoaderForPrimaryKeyTests.cs" />
7475
<Compile Include="BulkLoading\BulkLoaderGeneralTests.cs" />
76+
<Compile Include="BulkLoading\SqlBulkCopyUtilitySpy.cs" />
7577
<Compile Include="Data\SampleSurrogateKeyDifferentNamesDto.cs" />
7678
<Compile Include="Data\TestingDatabaseService.cs" />
7779
<Compile Include="Data\TestingDataGateway.cs" />

src/ivaldez.SqlBulkLoader/BulkLoader.cs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,15 @@ public BulkLoaderContext<T> InsertWithOptions<T>(
5555
/// <param name="conn">A SQL connection</param>
5656
/// <param name="keepIdentityColumnValue">If true, the bulk copy will attempt to insert into identity columns on the target table.</param>
5757
/// <param name="dataToInsert">The data that will be bulk loaded into the target table.</param>
58-
/// <param name="batchSize">The batch size of each bulk load.</param>
58+
/// <param name="batchSize">The batch size of each bulk load.</param>
59+
/// <param name="noBatch">Indicates that no batching should occur and all data should be written at once.</param>
5960
public void Insert<T>(
6061
string tableName,
6162
SqlConnection conn,
6263
bool keepIdentityColumnValue,
6364
IEnumerable<T> dataToInsert,
64-
int batchSize = 5000)
65+
int batchSize = 5000,
66+
bool noBatch = false)
6567
{
6668
Insert(
6769
tableName,
@@ -70,7 +72,8 @@ public void Insert<T>(
7072
dataToInsert,
7173
new List<string>(),
7274
new Dictionary<string, string>(),
73-
batchSize);
75+
batchSize,
76+
noBatch);
7477
}
7578

7679
/// <summary>
@@ -84,24 +87,44 @@ public void Insert<T>(
8487
/// <param name="propertiesToIgnore">A list of properties on the DTO to ignore.</param>
8588
/// <param name="renameFields">Pairs of source property names and mapped column names on the target table.</param>
8689
/// <param name="batchSize">The batch size of each bulk load.</param>
87-
public void Insert<T>(
88-
string tableName,
90+
/// <param name="noBatch">Indicates that no batching should occur and all data should be written at once.</param>
91+
public void Insert<T>(string tableName,
8992
SqlConnection conn,
9093
bool keepIdentityColumnValue,
9194
IEnumerable<T> dataToInsert,
9295
List<string> propertiesToIgnore,
9396
Dictionary<string, string> renameFields,
94-
int batchSize = 5000)
97+
int batchSize = 5000,
98+
bool noBatch = false)
9599
{
96100
var targetProperties = GetTargetProperties<T>(propertiesToIgnore, renameFields);
97101

98102
var options = SqlBulkCopyOptions.CheckConstraints | SqlBulkCopyOptions.TableLock;
99103

100104
if (keepIdentityColumnValue)
101105
{
102-
options = options | SqlBulkCopyOptions.KeepIdentity;
106+
options |= SqlBulkCopyOptions.KeepIdentity;
103107
}
104108

109+
if (noBatch)
110+
{
111+
BulkCopyWithNoBatching(tableName, conn, dataToInsert, options, targetProperties);
112+
}
113+
else
114+
{
115+
BulkCopyWithBatching(tableName, conn, dataToInsert, batchSize, options, targetProperties);
116+
}
117+
}
118+
119+
private void BulkCopyWithNoBatching<T>(string tableName, SqlConnection conn, IEnumerable<T> dataToInsert,
120+
SqlBulkCopyOptions options, TargetProperty[] targetProperties)
121+
{
122+
_sqlBulkCopyUtility.BulkCopy(tableName, conn, options, targetProperties, dataToInsert);
123+
}
124+
125+
private void BulkCopyWithBatching<T>(string tableName, SqlConnection conn, IEnumerable<T> dataToInsert, int batchSize,
126+
SqlBulkCopyOptions options, TargetProperty[] targetProperties)
127+
{
105128
var batch = new List<T>(batchSize);
106129

107130
foreach (var item in dataToInsert)
@@ -121,7 +144,7 @@ public void Insert<T>(
121144
batch.Clear();
122145
}
123146
}
124-
147+
125148
public class SqlBulkCopyUtility: ISqlBulkCopyUtility
126149
{
127150
public void BulkCopy<T>(string tableName, SqlConnection conn, SqlBulkCopyOptions options,

src/ivaldez.SqlBulkLoader/BulkLoaderContext.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class BulkLoaderContext<T>
1616

1717
private readonly List<string> _withoutMembers;
1818
private int _batchSize;
19+
private bool _noBatch;
1920

2021
public BulkLoaderContext(
2122
IBulkLoader bulkLoader,
@@ -72,6 +73,13 @@ public BulkLoaderContext<T> SetBatchSize(int value)
7273
return this;
7374
}
7475

76+
public BulkLoaderContext<T> NoBatch()
77+
{
78+
_noBatch = true;
79+
80+
return this;
81+
}
82+
7583
public void Execute()
7684
{
7785
_bulkLoader.Insert(
@@ -81,7 +89,8 @@ public void Execute()
8189
_dataToInsert,
8290
_withoutMembers,
8391
_renameFields,
84-
_batchSize);
92+
_batchSize,
93+
_noBatch);
8594
}
8695

8796
private string GetName(Expression<Func<T, object>> expression)

src/ivaldez.SqlBulkLoader/IBulkLoader.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ void Insert<T>(
1414
SqlConnection conn,
1515
bool keepIdentityColumnValue,
1616
IEnumerable<T> dataToInsert,
17-
int batchSize = 5000);
17+
int batchSize = 5000,
18+
bool noBatch = false);
1819

1920
BulkLoaderContext<T> InsertWithOptions<T>(
2021
string tableName,
@@ -23,13 +24,13 @@ BulkLoaderContext<T> InsertWithOptions<T>(
2324
IEnumerable<T> dataToInsert,
2425
int batchSize = 5000);
2526

26-
void Insert<T>(
27-
string tableName,
27+
void Insert<T>(string tableName,
2828
SqlConnection conn,
2929
bool keepIdentityColumnValue,
3030
IEnumerable<T> dataToInsert,
3131
List<string> propertiesToIgnore,
3232
Dictionary<string, string> renameFields,
33-
int batchSize = 5000);
33+
int batchSize = 5000,
34+
bool noBatch = false);
3435
}
3536
}

0 commit comments

Comments
 (0)