|
1 | 1 | using System.Collections.Generic;
|
| 2 | +using System.Threading; |
2 | 3 |
|
3 | 4 | namespace NHibernate.AdoNet
|
4 | 5 | {
|
5 |
| - /// <summary> Implementation of ColumnNameCache. </summary> |
| 6 | + /// <summary> Implementation of ColumnNameCache. Thread safe. </summary> |
6 | 7 | public class ColumnNameCache
|
7 | 8 | {
|
8 |
| - private readonly Dictionary<string, int?> columnNameToIndexCache; |
| 9 | + private readonly ReaderWriterLockSlim _cacheLock = new ReaderWriterLockSlim(); |
| 10 | + private readonly Dictionary<string, int> _columnNameToIndexCache; |
9 | 11 |
|
10 | 12 | public ColumnNameCache(int columnCount)
|
11 | 13 | {
|
12 | 14 | // 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); |
14 | 16 | }
|
15 | 17 |
|
16 | 18 | public int GetIndexForColumnName(string columnName, ResultSetWrapper rs)
|
17 | 19 | {
|
18 |
| - int? cached; |
19 |
| - columnNameToIndexCache.TryGetValue(columnName, out cached); |
20 |
| - if (cached.HasValue) |
| 20 | + int index; |
| 21 | + if (!TryRead(columnName, out index)) |
21 | 22 | {
|
22 |
| - return cached.Value; |
| 23 | + index = rs.Target.GetOrdinal(columnName); |
| 24 | + Insert(columnName, index); |
23 | 25 | }
|
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 |
25 | 51 | {
|
26 |
| - int index = rs.Target.GetOrdinal(columnName); |
27 |
| - columnNameToIndexCache[columnName] = index; |
28 |
| - return index; |
| 52 | + _cacheLock.ExitWriteLock(); |
29 | 53 | }
|
30 | 54 | }
|
31 | 55 | }
|
|
0 commit comments