Skip to content

Commit 280d4ba

Browse files
committed
Share table mappings and make thread safe
This fixes praeclarum#423 by guarding access to the mappings. It also fixes oysteinkrog#379 by making them static.
1 parent d2b144c commit 280d4ba

File tree

1 file changed

+28
-28
lines changed

1 file changed

+28
-28
lines changed

src/SQLite.cs

+28-28
Original file line numberDiff line numberDiff line change
@@ -163,16 +163,15 @@ public partial class SQLiteConnection : IDisposable
163163
{
164164
private bool _open;
165165
private TimeSpan _busyTimeout;
166-
private Dictionary<string, TableMapping> _mappings = null;
167-
private Dictionary<string, TableMapping> _tables = null;
166+
readonly static Dictionary<string, TableMapping> _mappings = new Dictionary<string, TableMapping> ();
168167
private System.Diagnostics.Stopwatch _sw;
169168
private long _elapsedMilliseconds = 0;
170169

171170
private int _transactionDepth = 0;
172171
private Random _rand = new Random ();
173172

174173
public Sqlite3DatabaseHandle Handle { get; private set; }
175-
internal static readonly Sqlite3DatabaseHandle NullHandle = default (Sqlite3DatabaseHandle);
174+
static readonly Sqlite3DatabaseHandle NullHandle = default (Sqlite3DatabaseHandle);
176175

177176
/// <summary>
178177
/// Gets the database path used by this connection.
@@ -345,7 +344,9 @@ public TimeSpan BusyTimeout {
345344
/// </summary>
346345
public IEnumerable<TableMapping> TableMappings {
347346
get {
348-
return _tables != null ? _tables.Values : Enumerable.Empty<TableMapping> ();
347+
lock (_mappings) {
348+
return new List<TableMapping> (_mappings.Values);
349+
}
349350
}
350351
}
351352

@@ -364,13 +365,19 @@ public IEnumerable<TableMapping> TableMappings {
364365
/// </returns>
365366
public TableMapping GetMapping (Type type, CreateFlags createFlags = CreateFlags.None)
366367
{
367-
if (_mappings == null) {
368-
_mappings = new Dictionary<string, TableMapping> ();
369-
}
370368
TableMapping map;
371-
if (!_mappings.TryGetValue (type.FullName, out map)) {
372-
map = new TableMapping (type, createFlags);
373-
_mappings[type.FullName] = map;
369+
var key = type.FullName;
370+
lock (_mappings) {
371+
if (_mappings.TryGetValue (key, out map)) {
372+
if (createFlags != CreateFlags.None && createFlags != map.CreateFlags) {
373+
map = new TableMapping (type, createFlags);
374+
_mappings[key] = map;
375+
}
376+
}
377+
else {
378+
map = new TableMapping (type, createFlags);
379+
_mappings.Add (key, map);
380+
}
374381
}
375382
return map;
376383
}
@@ -451,18 +458,11 @@ public CreateTableResult CreateTable<T> (CreateFlags createFlags = CreateFlags.N
451458
/// </returns>
452459
public CreateTableResult CreateTable (Type ty, CreateFlags createFlags = CreateFlags.None)
453460
{
454-
if (_tables == null) {
455-
_tables = new Dictionary<string, TableMapping> ();
456-
}
457-
TableMapping map;
458-
if (!_tables.TryGetValue (ty.FullName, out map)) {
459-
map = GetMapping (ty, createFlags);
460-
_tables.Add (ty.FullName, map);
461-
}
461+
var map = GetMapping (ty, createFlags);
462462

463463
// Present a nice error if no columns specified
464464
if (map.Columns.Length == 0) {
465-
throw new Exception (string.Format ("Cannot create a table with zero columns (does '{0}' have public properties?)", ty.FullName));
465+
throw new Exception (string.Format ("Cannot create a table without columns (does '{0}' have public properties?)", ty.FullName));
466466
}
467467

468468
// Check if the table exists
@@ -2100,13 +2100,16 @@ public class TableMapping
21002100

21012101
public string GetByPrimaryKeySql { get; private set; }
21022102

2103-
Column _autoPk;
2104-
Column[] _insertColumns;
2105-
Column[] _insertOrReplaceColumns;
2103+
public CreateFlags CreateFlags { get; private set; }
2104+
2105+
readonly Column _autoPk;
2106+
readonly Column[] _insertColumns;
2107+
readonly Column[] _insertOrReplaceColumns;
21062108

21072109
public TableMapping (Type type, CreateFlags createFlags = CreateFlags.None)
21082110
{
21092111
MappedType = type;
2112+
CreateFlags = createFlags;
21102113

21112114
var typeInfo = type.GetTypeInfo ();
21122115
var tableAttr =
@@ -2164,6 +2167,9 @@ from p in ti.DeclaredProperties
21642167
// People should not be calling Get/Find without a PK
21652168
GetByPrimaryKeySql = string.Format ("select * from \"{0}\" limit 1", TableName);
21662169
}
2170+
2171+
_insertColumns = Columns.Where (c => !c.IsAutoInc).ToArray ();
2172+
_insertOrReplaceColumns = Columns.ToArray ();
21672173
}
21682174

21692175
public bool HasAutoIncPK { get; private set; }
@@ -2177,18 +2183,12 @@ public void SetAutoIncPK (object obj, long id)
21772183

21782184
public Column[] InsertColumns {
21792185
get {
2180-
if (_insertColumns == null) {
2181-
_insertColumns = Columns.Where (c => !c.IsAutoInc).ToArray ();
2182-
}
21832186
return _insertColumns;
21842187
}
21852188
}
21862189

21872190
public Column[] InsertOrReplaceColumns {
21882191
get {
2189-
if (_insertOrReplaceColumns == null) {
2190-
_insertOrReplaceColumns = Columns.ToArray ();
2191-
}
21922192
return _insertOrReplaceColumns;
21932193
}
21942194
}

0 commit comments

Comments
 (0)