Skip to content

Commit 1014e35

Browse files
committed
Added an automatic flush when the max number of parameters are reached and renamed the batcher to a more universal name
1 parent 4a2a40c commit 1014e35

File tree

8 files changed

+417
-113
lines changed

8 files changed

+417
-113
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
using System;
2+
using System.Collections;
3+
using System.Linq;
4+
using log4net;
5+
using NHibernate.AdoNet;
6+
using NHibernate.Cfg;
7+
using NHibernate.Dialect;
8+
using NUnit.Framework;
9+
using Environment = NHibernate.Cfg.Environment;
10+
11+
namespace NHibernate.Test.Ado
12+
{
13+
[TestFixture]
14+
public class GenericBatchingBatcherFixture : TestCase
15+
{
16+
protected override string MappingsAssembly => "NHibernate.Test";
17+
18+
protected override IList Mappings => new[] {"Ado.VerySimple.hbm.xml"};
19+
20+
protected override void Configure(Configuration configuration)
21+
{
22+
configuration.SetProperty(Environment.BatchStrategy, typeof(GenericBatchingBatcherFactory).AssemblyQualifiedName);
23+
configuration.SetProperty(Environment.GenerateStatistics, "true");
24+
configuration.SetProperty(Environment.BatchSize, "1000");
25+
}
26+
27+
[Test]
28+
public void MassiveInsertUpdateDeleteTest()
29+
{
30+
var totalRecords = 1000;
31+
BatchInsert(totalRecords);
32+
BatchUpdate(totalRecords);
33+
BatchDelete(totalRecords);
34+
35+
DbShoudBeEmpty();
36+
}
37+
38+
[Test]
39+
public void BatchSizeTest()
40+
{
41+
using (var sqlLog = new SqlLogSpy())
42+
using (var s = Sfi.OpenSession())
43+
using (var tx = s.BeginTransaction())
44+
{
45+
s.SetBatchSize(5);
46+
for (var i = 0; i < 20; i++)
47+
{
48+
s.Save(new VerySimple { Id = 1 + i, Name = $"Fabio{i}", Weight = 1.45 + i });
49+
}
50+
tx.Commit();
51+
52+
var log = sqlLog.GetWholeLog();
53+
Assert.That(4, Is.EqualTo(FindAllOccurrences(log, "Batch commands:")));
54+
}
55+
Cleanup();
56+
}
57+
58+
private void BatchInsert(int totalRecords)
59+
{
60+
Sfi.Statistics.Clear();
61+
using (var s = Sfi.OpenSession())
62+
using (var tx = s.BeginTransaction())
63+
{
64+
for (var i = 0; i < totalRecords; i++)
65+
{
66+
s.Save(new VerySimple {Id = 1 + i, Name = $"Fabio{i}", Weight = 1.45 + i});
67+
}
68+
tx.Commit();
69+
}
70+
Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
71+
}
72+
73+
public void BatchUpdate(int totalRecords)
74+
{
75+
using (var s = Sfi.OpenSession())
76+
using (var tx = s.BeginTransaction())
77+
{
78+
var items = s.Query<VerySimple>().ToList();
79+
Assert.That(items.Count, Is.EqualTo(totalRecords));
80+
81+
foreach (var item in items)
82+
{
83+
item.Weight += 5;
84+
s.Update(item);
85+
}
86+
87+
Sfi.Statistics.Clear();
88+
tx.Commit();
89+
}
90+
Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
91+
}
92+
93+
public void BatchDelete(int totalRecords)
94+
{
95+
using (var s = Sfi.OpenSession())
96+
using (var tx = s.BeginTransaction())
97+
{
98+
var items = s.Query<VerySimple>().ToList();
99+
Assert.That(items.Count, Is.EqualTo(totalRecords));
100+
101+
foreach (var item in items)
102+
{
103+
s.Delete(item);
104+
}
105+
106+
Sfi.Statistics.Clear();
107+
tx.Commit();
108+
}
109+
Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
110+
}
111+
112+
private void DbShoudBeEmpty()
113+
{
114+
using (var s = Sfi.OpenSession())
115+
using (var tx = s.BeginTransaction())
116+
{
117+
var items = s.Query<VerySimple>().ToList();
118+
Assert.That(items.Count, Is.EqualTo(0));
119+
120+
tx.Commit();
121+
}
122+
}
123+
124+
private void Cleanup()
125+
{
126+
using (var s = Sfi.OpenSession())
127+
using (s.BeginTransaction())
128+
{
129+
s.CreateQuery("delete from VerySimple").ExecuteUpdate();
130+
s.Transaction.Commit();
131+
}
132+
}
133+
134+
private int FindAllOccurrences(string source, string substring)
135+
{
136+
if (source == null)
137+
{
138+
return 0;
139+
}
140+
int n = 0, count = 0;
141+
while ((n = source.IndexOf(substring, n, StringComparison.InvariantCulture)) != -1)
142+
{
143+
n += substring.Length;
144+
++count;
145+
}
146+
return count;
147+
}
148+
}
149+
}
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by AsyncGenerator.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
11+
using System;
12+
using System.Collections;
13+
using System.Linq;
14+
using log4net;
15+
using NHibernate.AdoNet;
16+
using NHibernate.Cfg;
17+
using NHibernate.Dialect;
18+
using NUnit.Framework;
19+
using Environment = NHibernate.Cfg.Environment;
20+
using NHibernate.Linq;
21+
22+
namespace NHibernate.Test.Ado
23+
{
24+
using System.Threading.Tasks;
25+
using System.Threading;
26+
[TestFixture]
27+
public class GenericBatchingBatcherFixtureAsync : TestCase
28+
{
29+
protected override string MappingsAssembly => "NHibernate.Test";
30+
31+
protected override IList Mappings => new[] {"Ado.VerySimple.hbm.xml"};
32+
33+
protected override void Configure(Configuration configuration)
34+
{
35+
configuration.SetProperty(Environment.BatchStrategy, typeof(GenericBatchingBatcherFactory).AssemblyQualifiedName);
36+
configuration.SetProperty(Environment.GenerateStatistics, "true");
37+
configuration.SetProperty(Environment.BatchSize, "1000");
38+
}
39+
40+
[Test]
41+
public async Task MassiveInsertUpdateDeleteTestAsync()
42+
{
43+
var totalRecords = 1000;
44+
await (BatchInsertAsync(totalRecords));
45+
await (BatchUpdateAsync(totalRecords));
46+
await (BatchDeleteAsync(totalRecords));
47+
48+
await (DbShoudBeEmptyAsync());
49+
}
50+
51+
[Test]
52+
public async Task BatchSizeTestAsync()
53+
{
54+
using (var sqlLog = new SqlLogSpy())
55+
using (var s = Sfi.OpenSession())
56+
using (var tx = s.BeginTransaction())
57+
{
58+
s.SetBatchSize(5);
59+
for (var i = 0; i < 20; i++)
60+
{
61+
await (s.SaveAsync(new VerySimple { Id = 1 + i, Name = $"Fabio{i}", Weight = 1.45 + i }));
62+
}
63+
await (tx.CommitAsync());
64+
65+
var log = sqlLog.GetWholeLog();
66+
Assert.That(4, Is.EqualTo(FindAllOccurrences(log, "Batch commands:")));
67+
}
68+
await (CleanupAsync());
69+
}
70+
71+
private async Task BatchInsertAsync(int totalRecords, CancellationToken cancellationToken = default(CancellationToken))
72+
{
73+
Sfi.Statistics.Clear();
74+
using (var s = Sfi.OpenSession())
75+
using (var tx = s.BeginTransaction())
76+
{
77+
for (var i = 0; i < totalRecords; i++)
78+
{
79+
await (s.SaveAsync(new VerySimple {Id = 1 + i, Name = $"Fabio{i}", Weight = 1.45 + i}, cancellationToken));
80+
}
81+
await (tx.CommitAsync(cancellationToken));
82+
}
83+
Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
84+
}
85+
86+
public async Task BatchUpdateAsync(int totalRecords, CancellationToken cancellationToken = default(CancellationToken))
87+
{
88+
using (var s = Sfi.OpenSession())
89+
using (var tx = s.BeginTransaction())
90+
{
91+
var items = await (s.Query<VerySimple>().ToListAsync(cancellationToken));
92+
Assert.That(items.Count, Is.EqualTo(totalRecords));
93+
94+
foreach (var item in items)
95+
{
96+
item.Weight += 5;
97+
await (s.UpdateAsync(item, cancellationToken));
98+
}
99+
100+
Sfi.Statistics.Clear();
101+
await (tx.CommitAsync(cancellationToken));
102+
}
103+
Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
104+
}
105+
106+
public async Task BatchDeleteAsync(int totalRecords, CancellationToken cancellationToken = default(CancellationToken))
107+
{
108+
using (var s = Sfi.OpenSession())
109+
using (var tx = s.BeginTransaction())
110+
{
111+
var items = await (s.Query<VerySimple>().ToListAsync(cancellationToken));
112+
Assert.That(items.Count, Is.EqualTo(totalRecords));
113+
114+
foreach (var item in items)
115+
{
116+
await (s.DeleteAsync(item, cancellationToken));
117+
}
118+
119+
Sfi.Statistics.Clear();
120+
await (tx.CommitAsync(cancellationToken));
121+
}
122+
Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
123+
}
124+
125+
private async Task DbShoudBeEmptyAsync(CancellationToken cancellationToken = default(CancellationToken))
126+
{
127+
using (var s = Sfi.OpenSession())
128+
using (var tx = s.BeginTransaction())
129+
{
130+
var items = await (s.Query<VerySimple>().ToListAsync(cancellationToken));
131+
Assert.That(items.Count, Is.EqualTo(0));
132+
133+
await (tx.CommitAsync(cancellationToken));
134+
}
135+
}
136+
137+
private async Task CleanupAsync(CancellationToken cancellationToken = default(CancellationToken))
138+
{
139+
using (var s = Sfi.OpenSession())
140+
using (s.BeginTransaction())
141+
{
142+
await (s.CreateQuery("delete from VerySimple").ExecuteUpdateAsync(cancellationToken));
143+
await (s.Transaction.CommitAsync(cancellationToken));
144+
}
145+
}
146+
147+
private int FindAllOccurrences(string source, string substring)
148+
{
149+
if (source == null)
150+
{
151+
return 0;
152+
}
153+
int n = 0, count = 0;
154+
while ((n = source.IndexOf(substring, n, StringComparison.InvariantCulture)) != -1)
155+
{
156+
n += substring.Length;
157+
++count;
158+
}
159+
return count;
160+
}
161+
}
162+
}

src/NHibernate.Test/Async/TypesTest/AbstractDateTimeTypeFixture.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,10 @@ public virtual async Task SaveUseExpectedSqlTypeAsync()
248248
}
249249

250250
var expected = 3;
251-
// PostgreSQL batcher uses IDriver.GenerateCommand method to create the batching command,
251+
// GenericBatchingBatcher uses IDriver.GenerateCommand method to create the batching command,
252252
// so the expected result will be doubled as GenerateCommand calls IDriver.GenerateParameter
253253
// for each parameter.
254-
if (Sfi.Settings.BatcherFactory is PostgreSQLClientBatchingBatcherFactory)
254+
if (Sfi.Settings.BatcherFactory is GenericBatchingBatcherFactory)
255255
{
256256
expected *= 2;
257257
}

src/NHibernate.Test/TypesTest/AbstractDateTimeTypeFixture.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,10 +279,10 @@ public virtual void SaveUseExpectedSqlType()
279279
}
280280

281281
var expected = 3;
282-
// PostgreSQL batcher uses IDriver.GenerateCommand method to create the batching command,
282+
// GenericBatchingBatcher uses IDriver.GenerateCommand method to create the batching command,
283283
// so the expected result will be doubled as GenerateCommand calls IDriver.GenerateParameter
284284
// for each parameter.
285-
if (Sfi.Settings.BatcherFactory is PostgreSQLClientBatchingBatcherFactory)
285+
if (Sfi.Settings.BatcherFactory is GenericBatchingBatcherFactory)
286286
{
287287
expected *= 2;
288288
}

0 commit comments

Comments
 (0)