Skip to content

Commit 938702c

Browse files
committed
Fix NH-3420: Merge branch 'grzpas-3.1.0GA_column-cache-concurency-fix'
2 parents ebcd347 + 0c2e312 commit 938702c

File tree

1 file changed

+35
-11
lines changed

1 file changed

+35
-11
lines changed

src/NHibernate/AdoNet/ColumnNameCache.cs

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,55 @@
11
using System.Collections.Generic;
2+
using System.Threading;
23

34
namespace NHibernate.AdoNet
45
{
5-
/// <summary> Implementation of ColumnNameCache. </summary>
6+
/// <summary> Implementation of ColumnNameCache. Thread safe. </summary>
67
public class ColumnNameCache
78
{
8-
private readonly Dictionary<string, int?> columnNameToIndexCache;
9+
private readonly ReaderWriterLockSlim _cacheLock = new ReaderWriterLockSlim();
10+
private readonly Dictionary<string, int> _columnNameToIndexCache;
911

1012
public ColumnNameCache(int columnCount)
1113
{
1214
// should *not* need to grow beyond the size of the total number of columns in the rs
13-
columnNameToIndexCache = new Dictionary<string, int?>(columnCount);
15+
_columnNameToIndexCache = new Dictionary<string, int>(columnCount);
1416
}
1517

1618
public int GetIndexForColumnName(string columnName, ResultSetWrapper rs)
1719
{
18-
int? cached;
19-
columnNameToIndexCache.TryGetValue(columnName, out cached);
20-
if (cached.HasValue)
20+
int index;
21+
if (!TryRead(columnName, out index))
2122
{
22-
return cached.Value;
23+
index = rs.Target.GetOrdinal(columnName);
24+
Insert(columnName, index);
2325
}
24-
else
26+
27+
return index;
28+
}
29+
30+
private bool TryRead(string key, out int value)
31+
{
32+
_cacheLock.EnterReadLock();
33+
try
34+
{
35+
return _columnNameToIndexCache.TryGetValue(key, out value);
36+
}
37+
finally
38+
{
39+
_cacheLock.ExitReadLock();
40+
}
41+
}
42+
43+
private void Insert(string key, int value)
44+
{
45+
_cacheLock.EnterWriteLock();
46+
try
47+
{
48+
_columnNameToIndexCache[key] = value;
49+
}
50+
finally
2551
{
26-
int index = rs.Target.GetOrdinal(columnName);
27-
columnNameToIndexCache[columnName] = index;
28-
return index;
52+
_cacheLock.ExitWriteLock();
2953
}
3054
}
3155
}

0 commit comments

Comments
 (0)