Skip to content

Commit 0225ccd

Browse files
NH-4013 - Test case and fix for SQL-Server batcher failure after CloseCommands.
1 parent 33e71cb commit 0225ccd

File tree

6 files changed

+126
-12
lines changed

6 files changed

+126
-12
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using NHibernate.Cfg;
5+
using NHibernate.Util;
6+
using NUnit.Framework;
7+
using Environment = NHibernate.Cfg.Environment;
8+
9+
namespace NHibernate.Test.ConnectionTest
10+
{
11+
[TestFixture]
12+
public class BatcherFixture : ConnectionManagementTestCase
13+
{
14+
protected override void Configure(Configuration config)
15+
{
16+
base.Configure(config);
17+
config.SetProperty(Environment.BatchSize, "10");
18+
}
19+
20+
protected override ISession GetSessionUnderTest()
21+
=> OpenSession();
22+
23+
protected override void OnTearDown()
24+
{
25+
using (var s = OpenSession())
26+
{
27+
s.CreateQuery("delete from System.Object").ExecuteUpdate();
28+
}
29+
}
30+
31+
[Test]
32+
public void CanCloseCommandsAndUseBatcher()
33+
{
34+
using (var s = OpenSession())
35+
{
36+
// Need a generator strategy not causing insert at save.
37+
var silly = new YetAnother { Name = "Silly" };
38+
s.Save(silly);
39+
s.GetSessionImplementation().ConnectionManager.Batcher.CloseCommands();
40+
41+
Assert.DoesNotThrow(s.Flush, "Flush failure after closing commands.");
42+
}
43+
}
44+
}
45+
}

src/NHibernate.Test/ConnectionTest/Silly.hbm.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,11 @@
1616
</id>
1717
<property name="Name"/>
1818
</class>
19+
20+
<class name="YetAnother">
21+
<id name="Id" type="long">
22+
<generator class="hilo"/>
23+
</id>
24+
<property name="Name"/>
25+
</class>
1926
</hibernate-mapping>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
3+
namespace NHibernate.Test.ConnectionTest
4+
{
5+
[Serializable]
6+
public class YetAnother
7+
{
8+
public virtual long Id { get; set; }
9+
10+
public virtual string Name { get; set; }
11+
}
12+
}

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,10 @@
202202
<Compile Include="CompositeId\Order.cs" />
203203
<Compile Include="CompositeId\Product.cs" />
204204
<Compile Include="ConnectionStringTest\NamedConnectionStringFixture.cs" />
205+
<Compile Include="ConnectionTest\BatcherFixture.cs" />
205206
<Compile Include="ConnectionTest\AggressiveReleaseTest.cs" />
206207
<Compile Include="ConnectionTest\ConnectionManagementTestCase.cs" />
208+
<Compile Include="ConnectionTest\YetAnother.cs" />
207209
<Compile Include="ConnectionTest\Other.cs" />
208210
<Compile Include="ConnectionTest\Silly.cs" />
209211
<Compile Include="ConnectionTest\MapBasedSessionContextFixture.cs" />

src/NHibernate/AdoNet/MySqlClientBatchingBatcher.cs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ protected override void DoExecuteBatch(DbCommand ps)
7474
if (Factory.Settings.SqlStatementLogger.IsDebugEnabled)
7575
{
7676
Factory.Settings.SqlStatementLogger.LogBatchCommand(currentBatchCommandsLog.ToString());
77-
currentBatchCommandsLog = new StringBuilder().AppendLine("Batch commands:");
7877
}
7978

8079
int rowsAffected;
@@ -89,28 +88,53 @@ protected override void DoExecuteBatch(DbCommand ps)
8988

9089
Expectations.VerifyOutcomeBatched(totalExpectedRowsAffected, rowsAffected);
9190

92-
currentBatch.Dispose();
93-
totalExpectedRowsAffected = 0;
94-
currentBatch = CreateConfiguredBatch();
91+
ClearCurrentBatch();
9592
}
9693

9794
private MySqlClientSqlCommandSet CreateConfiguredBatch()
9895
{
9996
return new MySqlClientSqlCommandSet(batchSize);
10097
}
10198

99+
private void ClearCurrentBatch()
100+
{
101+
currentBatch.Dispose();
102+
totalExpectedRowsAffected = 0;
103+
currentBatch = CreateConfiguredBatch();
104+
105+
if (Factory.Settings.SqlStatementLogger.IsDebugEnabled)
106+
{
107+
currentBatchCommandsLog = new StringBuilder().AppendLine("Batch commands:");
108+
}
109+
}
110+
102111
public override void CloseCommands()
103112
{
104113
base.CloseCommands();
105114

106115
try
107116
{
108-
currentBatch.Dispose();
117+
ClearCurrentBatch();
109118
}
110119
catch (Exception e)
111120
{
112-
// Prevent exceptions when closing the batch from hiding any original exception
121+
// Prevent exceptions when clearing the batch from hiding any original exception
113122
// (We do not know here if this batch closing occurs after a failure or not.)
123+
Log.Warn("Exception clearing batch", e);
124+
}
125+
}
126+
127+
protected override void Dispose(bool isDisposing)
128+
{
129+
base.Dispose(isDisposing);
130+
// Prevent exceptions when closing the batch from hiding any original exception
131+
// (We do not know here if this batch closing occurs after a failure or not.)
132+
try
133+
{
134+
currentBatch.Dispose();
135+
}
136+
catch (Exception e)
137+
{
114138
Log.Warn("Exception closing batcher", e);
115139
}
116140
}

src/NHibernate/AdoNet/SqlClientBatchingBatcher.cs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ protected override void DoExecuteBatch(DbCommand ps)
7777
if (Factory.Settings.SqlStatementLogger.IsDebugEnabled)
7878
{
7979
Factory.Settings.SqlStatementLogger.LogBatchCommand(_currentBatchCommandsLog.ToString());
80-
_currentBatchCommandsLog = new StringBuilder().AppendLine("Batch commands:");
8180
}
8281

8382
int rowsAffected;
@@ -92,9 +91,7 @@ protected override void DoExecuteBatch(DbCommand ps)
9291

9392
Expectations.VerifyOutcomeBatched(_totalExpectedRowsAffected, rowsAffected);
9493

95-
_currentBatch.Dispose();
96-
_totalExpectedRowsAffected = 0;
97-
_currentBatch = CreateConfiguredBatch();
94+
ClearCurrentBatch();
9895
}
9996

10097
private SqlClientSqlCommandSet CreateConfiguredBatch()
@@ -118,18 +115,45 @@ private SqlClientSqlCommandSet CreateConfiguredBatch()
118115
return result;
119116
}
120117

118+
private void ClearCurrentBatch()
119+
{
120+
_currentBatch.Dispose();
121+
_totalExpectedRowsAffected = 0;
122+
_currentBatch = CreateConfiguredBatch();
123+
124+
if (Factory.Settings.SqlStatementLogger.IsDebugEnabled)
125+
{
126+
_currentBatchCommandsLog = new StringBuilder().AppendLine("Batch commands:");
127+
}
128+
}
129+
121130
public override void CloseCommands()
122131
{
123132
base.CloseCommands();
124133

134+
// Prevent exceptions when closing the batch from hiding any original exception
135+
// (We do not know here if this batch closing occurs after a failure or not.)
136+
try
137+
{
138+
ClearCurrentBatch();
139+
}
140+
catch (Exception e)
141+
{
142+
Log.Warn("Exception clearing batch", e);
143+
}
144+
}
145+
146+
protected override void Dispose(bool isDisposing)
147+
{
148+
base.Dispose(isDisposing);
149+
// Prevent exceptions when closing the batch from hiding any original exception
150+
// (We do not know here if this batch closing occurs after a failure or not.)
125151
try
126152
{
127153
_currentBatch.Dispose();
128154
}
129155
catch (Exception e)
130156
{
131-
// Prevent exceptions when closing the batch from hiding any original exception
132-
// (We do not know here if this batch closing occurs after a failure or not.)
133157
Log.Warn("Exception closing batcher", e);
134158
}
135159
}

0 commit comments

Comments
 (0)