Skip to content

Commit b39ded0

Browse files
committed
Change IncrementGenerator to use the Session.Batcher instead of creating a brand new connection to retrieve the next value
See https://nhibernate.jira.com/browse/NH-3591 for details
1 parent 770ab3c commit b39ded0

File tree

4 files changed

+103
-19
lines changed

4 files changed

+103
-19
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
using NHibernate.Driver;
2+
using NUnit.Framework;
3+
using SharpTestsEx;
4+
5+
namespace NHibernate.Test.DriverTest
6+
{
7+
[TestFixture]
8+
public class FirebirdClientDriverFixture
9+
{
10+
#region Fields
11+
private string _connectionString;
12+
private FirebirdClientDriver _driver;
13+
#endregion
14+
15+
#region Tests
16+
17+
[Test]
18+
public void ConnectionPooling_OpenThenCloseThenOpenAnotherOne_OnlyOneConnectionIsPooled()
19+
{
20+
MakeDriver();
21+
var connection1 = _driver.CreateConnection();
22+
var connection2 = _driver.CreateConnection();
23+
connection1.ConnectionString = _connectionString;
24+
connection2.ConnectionString = _connectionString;
25+
26+
connection1.Open();
27+
//return the connection1 to the pool
28+
connection1.Close();
29+
//open the second connection
30+
connection2.Open();
31+
32+
var physicalConnections = GetEstablishedConnections();
33+
physicalConnections.Should().Be(1);
34+
}
35+
36+
[Test]
37+
public void ConnectionPooling_OpenThenCloseTwoAtTheSameTime_TowConnectionsArePooled()
38+
{
39+
MakeDriver();
40+
var connection1 = _driver.CreateConnection();
41+
var connection2 = _driver.CreateConnection();
42+
connection1.ConnectionString = _connectionString;
43+
connection2.ConnectionString = _connectionString;
44+
45+
connection1.Open();
46+
connection2.Open();
47+
//return both to the pool
48+
connection1.Close();
49+
connection2.Close();
50+
51+
var physicalConnections = GetEstablishedConnections();
52+
physicalConnections.Should().Be(2);
53+
}
54+
55+
#endregion
56+
57+
#region Private Members
58+
private void MakeDriver()
59+
{
60+
var cfg = TestConfigurationHelper.GetDefaultConfiguration();
61+
var dlct = cfg.GetProperty("dialect");
62+
if (!dlct.Contains("Firebird"))
63+
Assert.Ignore("Applies only to Firebird");
64+
65+
_driver = new FirebirdClientDriver();
66+
_connectionString = cfg.GetProperty("connection.connection_string");
67+
}
68+
69+
private int GetEstablishedConnections()
70+
{
71+
using (var conn = _driver.CreateConnection())
72+
{
73+
conn.ConnectionString = _connectionString;
74+
conn.Open();
75+
using (var cmd = conn.CreateCommand())
76+
{
77+
cmd.CommandText = "select count(*) from mon$attachments where mon$attachment_id <> current_connection";
78+
return (int)cmd.ExecuteScalar();
79+
}
80+
}
81+
}
82+
#endregion
83+
}
84+
}

src/NHibernate.Test/NHSpecificTest/NH1061/Fixture.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ public void IncrementGeneratorShouldIncludeClassLevelSchemaWhenGettingNextId()
3131
// think this would be a huge problem.
3232
// Having said that, if someone sees this and have a better idea to test,
3333
// please feel free to change it.
34-
FieldInfo sqlFieldInfo = generator.GetType().GetField("sql", BindingFlags.NonPublic | BindingFlags.Instance);
35-
string sql = (string)sqlFieldInfo.GetValue(generator);
34+
FieldInfo sqlFieldInfo = generator.GetType().GetField("_sql", BindingFlags.NonPublic | BindingFlags.Instance);
35+
string sql = sqlFieldInfo.GetValue(generator).ToString();
3636

3737
Assert.AreEqual("select max(Id) from test.TestNH1061", sql);
3838
}

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@
222222
<Compile Include="DialectTest\MsSqlCe40DialectFixture.cs" />
223223
<Compile Include="DialectTest\SchemaTests\ColumnMetaDataFixture.cs" />
224224
<Compile Include="DriverTest\DbProviderFactoryDriveConnectionCommandProviderTest.cs" />
225+
<Compile Include="DriverTest\FirebirdClientDriverFixture.cs" />
225226
<Compile Include="DriverTest\ReflectionBasedDriverTest.cs" />
226227
<Compile Include="DriverTest\Sql2008DateTime2Test.cs" />
227228
<Compile Include="DriverTest\SqlClientDriverFixture.cs" />

src/NHibernate/Id/IncrementGenerator.cs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Data;
4+
using System.Data.Common;
45
using System.Runtime.CompilerServices;
56
using System.Text;
6-
77
using NHibernate.Engine;
88
using NHibernate.Exceptions;
9+
using NHibernate.SqlCommand;
10+
using NHibernate.SqlTypes;
911
using NHibernate.Type;
10-
using NHibernate.Util;
11-
using System.Data.Common;
1212

1313
namespace NHibernate.Id
1414
{
@@ -30,7 +30,7 @@ public class IncrementGenerator : IIdentifierGenerator, IConfigurable
3030
private static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof(IncrementGenerator));
3131

3232
private long next;
33-
private string sql;
33+
private SqlString _sql;
3434
private System.Type returnClass;
3535

3636
/// <summary>
@@ -72,7 +72,8 @@ public void Configure(IType type, IDictionary<string, string> parms, Dialect.Dia
7272
column = "ids_." + column;
7373
}
7474

75-
sql = "select max(" + column + ") from " + buf;
75+
var sqlTxt = string.Format("select max({0}) from {1}", column, buf);
76+
_sql = new SqlString(sqlTxt);
7677
}
7778

7879
/// <summary>
@@ -84,7 +85,7 @@ public void Configure(IType type, IDictionary<string, string> parms, Dialect.Dia
8485
[MethodImpl(MethodImplOptions.Synchronized)]
8586
public object Generate(ISessionImplementor session, object obj)
8687
{
87-
if (sql != null)
88+
if (_sql != null)
8889
{
8990
GetNext(session);
9091
}
@@ -93,38 +94,36 @@ public object Generate(ISessionImplementor session, object obj)
9394

9495
private void GetNext(ISessionImplementor session)
9596
{
96-
log.Debug("fetching initial value: " + sql);
97+
log.Debug("fetching initial value: " + _sql);
9798

9899
try
99100
{
100-
IDbConnection conn = session.Factory.ConnectionProvider.GetConnection();
101-
IDbCommand qps = conn.CreateCommand();
102-
qps.CommandText = sql;
103-
qps.CommandType = CommandType.Text;
101+
var cmd = session.Batcher.PrepareCommand(CommandType.Text, _sql, SqlTypeFactory.NoTypes);
102+
IDataReader reader = null;
104103
try
105104
{
106-
IDataReader rs = qps.ExecuteReader();
105+
reader = session.Batcher.ExecuteReader(cmd);
107106
try
108107
{
109-
if (rs.Read())
108+
if (reader.Read())
110109
{
111-
next = !rs.IsDBNull(0) ? Convert.ToInt64(rs.GetValue(0)) + 1 : 1L;
110+
next = !reader.IsDBNull(0) ? Convert.ToInt64(reader.GetValue(0)) + 1 : 1L;
112111
}
113112
else
114113
{
115114
next = 1L;
116115
}
117-
sql = null;
116+
_sql = null;
118117
log.Debug("first free id: " + next);
119118
}
120119
finally
121120
{
122-
rs.Close();
121+
reader.Close();
123122
}
124123
}
125124
finally
126125
{
127-
session.Factory.ConnectionProvider.CloseConnection(conn);
126+
session.Batcher.CloseCommand(cmd, reader);
128127
}
129128
}
130129
catch (DbException sqle)

0 commit comments

Comments
 (0)