Skip to content

Commit a46fb12

Browse files
ngbrownoskarb
authored andcommitted
NH-3897 - Makes DebugConnectionProvider.connections thread safe. (#495)
Fixes NH-3436 failing for me when multiple threads try to extend the HashSet at the same time.
1 parent d14ea68 commit a46fb12

File tree

1 file changed

+15
-36
lines changed

1 file changed

+15
-36
lines changed
Lines changed: 15 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using System;
2-
using System.Collections;
3-
using System.Collections.Generic;
2+
using System.Collections.Concurrent;
43
using System.Data;
4+
using System.Linq;
55
using NHibernate.Connection;
66

77
namespace NHibernate.Test
@@ -12,70 +12,49 @@ namespace NHibernate.Test
1212
/// </summary>
1313
public class DebugConnectionProvider : DriverConnectionProvider
1414
{
15-
private ISet<IDbConnection> connections = new HashSet<IDbConnection>();
15+
private ConcurrentDictionary<IDbConnection, byte> connections = new ConcurrentDictionary<IDbConnection, byte>();
1616

1717
public override IDbConnection GetConnection()
1818
{
1919
try
2020
{
2121
IDbConnection connection = base.GetConnection();
22-
connections.Add(connection);
22+
connections.TryAdd(connection, 0);
2323
return connection;
2424
}
2525
catch (Exception e)
2626
{
2727
throw new HibernateException("Could not open connection to: " + ConnectionString, e);
2828
}
29-
3029
}
3130

3231
public override void CloseConnection(IDbConnection conn)
3332
{
3433
base.CloseConnection(conn);
35-
connections.Remove(conn);
34+
byte _;
35+
connections.TryRemove(conn, out _);
3636
}
3737

3838
public bool HasOpenConnections
3939
{
4040
get
4141
{
42-
// check to see if all connections that were at one point opened
43-
// have been closed through the CloseConnection
44-
// method
45-
if (connections.Count == 0)
46-
{
47-
// there are no connections, either none were opened or
48-
// all of the closings went through CloseConnection.
49-
return false;
50-
}
51-
else
52-
{
53-
// Disposing of an ISession does not call CloseConnection (should it???)
54-
// so a Diposed of ISession will leave an IDbConnection in the list but
55-
// the IDbConnection will be closed (atleast with MsSql it works this way).
56-
foreach (IDbConnection conn in connections)
57-
{
58-
if (conn.State != ConnectionState.Closed)
59-
{
60-
return true;
61-
}
62-
}
63-
64-
// all of the connections have been Disposed and were closed that way
65-
// or they were Closed through the CloseConnection method.
66-
return false;
67-
}
42+
// Disposing of an ISession does not call CloseConnection (should it???)
43+
// so a Diposed of ISession will leave an IDbConnection in the list but
44+
// the IDbConnection will be closed (atleast with MsSql it works this way).
45+
return connections.Keys.Any(conn => conn.State != ConnectionState.Closed);
6846
}
6947
}
7048

7149
public void CloseAllConnections()
7250
{
7351
while (connections.Count != 0)
7452
{
75-
IEnumerator en = connections.GetEnumerator();
76-
en.MoveNext();
77-
CloseConnection(en.Current as IDbConnection);
53+
foreach (var conn in connections.Keys.ToArray())
54+
{
55+
CloseConnection(conn);
56+
}
7857
}
7958
}
8059
}
81-
}
60+
}

0 commit comments

Comments
 (0)