Skip to content

Commit 4cb66a3

Browse files
committed
v0.1.3
1 parent 973fe42 commit 4cb66a3

File tree

5 files changed

+46
-56
lines changed

5 files changed

+46
-56
lines changed

src/NuExt.System.Data.SQLite.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ System.Data.SQLite.SQLiteDbConnection
1414
System.Data.SQLite.SQLiteDbContext
1515
System.Data.SQLite.SQLiteDbConverter
1616
System.Data.SQLite.SQLiteDbTransaction</Description>
17-
<Version>0.1.2</Version>
17+
<Version>0.1.3</Version>
1818
<RootNamespace />
1919
<GenerateDocumentationFile>True</GenerateDocumentationFile>
2020
<NoWarn>$(NoWarn);1591</NoWarn>
@@ -24,11 +24,11 @@ System.Data.SQLite.SQLiteDbTransaction</Description>
2424
</PropertyGroup>
2525

2626
<ItemGroup>
27-
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.118" />
27+
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.119" />
2828
</ItemGroup>
2929

3030
<ItemGroup Condition="'$(UseNuExtPackages)' == 'true'">
31-
<PackageReference Include="NuExt.System.Data" Version="0.1.2" />
31+
<PackageReference Include="NuExt.System.Data" Version="0.1.3" />
3232
</ItemGroup>
3333

3434
<ItemGroup Condition="'$(UseNuExtPackages)' == 'false'">

src/System/Data/SQLite/SQLiteDbConnection.Transactions.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,31 @@ partial class SQLiteDbConnection
1010
public SQLiteDbTransaction BeginTransaction()
1111
{
1212
CheckDisposed();
13-
Debug.Assert(_inTransaction == 0);
14-
Interlocked.Increment(ref _inTransaction);
13+
Debug.Assert(TransactionCount == 0, "Transaction count should be zero before starting a new transaction.");
14+
Throw.InvalidOperationExceptionIf(InTransaction, "SQLite does not support nested transactions");
1515
try
1616
{
17-
return new SQLiteDbTransaction(this, _conn.BeginTransaction(), () => Interlocked.Decrement(ref _inTransaction));
17+
return new SQLiteDbTransaction(this, _conn.BeginTransaction());
1818
}
1919
catch (Exception ex)
2020
{
2121
Debug.Assert(_assertsDisabled, ex.GetType() + ": " + ex.Message);
22-
Interlocked.Decrement(ref _inTransaction);
2322
throw;
2423
}
2524
}
2625

2726
public SQLiteDbTransaction BeginTransaction(IsolationLevel isolationLevel)
2827
{
2928
CheckDisposed();
30-
Debug.Assert(_inTransaction == 0);
31-
Interlocked.Increment(ref _inTransaction);
29+
Debug.Assert(TransactionCount == 0, "Transaction count should be zero before starting a new transaction.");
30+
Throw.InvalidOperationExceptionIf(InTransaction, "SQLite does not support nested transactions");
3231
try
3332
{
34-
return new SQLiteDbTransaction(this, _conn.BeginTransaction(isolationLevel), () => Interlocked.Decrement(ref _inTransaction));
33+
return new SQLiteDbTransaction(this, _conn.BeginTransaction(isolationLevel));
3534
}
3635
catch (Exception ex)
3736
{
3837
Debug.Assert(_assertsDisabled, ex.GetType() + ": " + ex.Message);
39-
Interlocked.Decrement(ref _inTransaction);
4038
throw;
4139
}
4240
}

src/System/Data/SQLite/SQLiteDbConnection.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public sealed partial class SQLiteDbConnection : Disposable, IDbConnection
1414
{
1515
private readonly SQLiteConnection _conn;
1616
private SQLiteDbConnectionFactory.AsyncLockCounter _syncRoot;
17-
private volatile int _inTransaction;
17+
internal volatile int TransactionCount;
1818

1919
/// <summary>
2020
/// Initializes the connection with the specified connection string.
@@ -37,12 +37,12 @@ public SQLiteDbConnection(string connectionString, bool useSharedLock)
3737
#else
3838
Throw.IfNullOrEmpty(connectionString);
3939
#endif
40-
_ = new SQLiteConnectionStringBuilder(connectionString);//throws if connection string is invalid
40+
var csb = new SQLiteConnectionStringBuilder(connectionString);//throws if connection string is invalid
4141
_conn = new SQLiteConnection(connectionString);
4242
UseSharedLock = useSharedLock;
4343
if (useSharedLock)
4444
{
45-
_syncRoot = SQLiteDbConnectionFactory.Instance.GetSyncObj(connectionString);
45+
_syncRoot = SQLiteDbConnectionFactory.Instance.GetSyncObj(csb.DataSource);
4646
}
4747
else
4848
{
@@ -66,7 +66,7 @@ public int DefaultTimeout
6666
set => _conn.DefaultTimeout = value;
6767
}
6868

69-
public bool InTransaction => _inTransaction > 0;
69+
public bool InTransaction => TransactionCount > 0;
7070

7171
/// <summary>
7272
/// Determines whether the current connection holds the database lock.
@@ -125,15 +125,14 @@ public void Close(ConnectionState originalState)
125125
protected override void OnDispose()
126126
{
127127
Close();
128-
var connectionString = _conn.ConnectionString;
129128
_conn.Dispose();
130129

131130
var syncRoot = Interlocked.Exchange(ref _syncRoot!, null);
132131
if (syncRoot != null)
133132
{
134133
if (UseSharedLock)
135134
{
136-
if (SQLiteDbConnectionFactory.Instance.TryRelease(connectionString))
135+
if (SQLiteDbConnectionFactory.Instance.TryRelease(syncRoot.DataSource!))
137136
{
138137
Debug.Assert(syncRoot.IsDisposed);
139138
}

src/System/Data/SQLite/SQLiteDbConnectionFactory.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ internal class SQLiteDbConnectionFactory
66

77
internal class AsyncLockCounter : Disposable
88
{
9-
public readonly ReentrantAsyncLock Mutex = new();
10-
public volatile int ReferenceCount;
9+
internal readonly ReentrantAsyncLock Mutex = new();
10+
internal volatile int ReferenceCount;
11+
internal string? DataSource;
1112
#if DEBUG
12-
public bool IsExpired => ReferenceCount <= 0;
13+
internal bool IsExpired => ReferenceCount <= 0;
1314
#endif
1415
protected override void OnDispose()
1516
{
@@ -43,28 +44,28 @@ private SQLiteDbConnectionFactory()
4344
/// <summary>
4445
/// Gets an object that can be used to synchronize access to the database.
4546
/// </summary>
46-
internal AsyncLockCounter GetSyncObj(string connectionString)
47+
internal AsyncLockCounter GetSyncObj(string dataSource)
4748
{
4849
AsyncLockCounter? syncObject;
4950
lock (_sharedLocks)
5051
{
51-
if (!_sharedLocks.TryGetValue(connectionString, out syncObject))
52+
if (!_sharedLocks.TryGetValue(dataSource, out syncObject))
5253
{
53-
_sharedLocks.Add(connectionString, syncObject = new AsyncLockCounter());
54+
_sharedLocks.Add(dataSource, syncObject = new AsyncLockCounter() { DataSource = dataSource });
5455
}
5556
Interlocked.Increment(ref syncObject.ReferenceCount);
5657
}
5758
return syncObject;
5859
}
5960

60-
internal bool TryRelease(string connectionString)
61+
internal bool TryRelease(string dataSource)
6162
{
6263
lock (_sharedLocks)
6364
{
64-
if (_sharedLocks.TryGetValue(connectionString, out var syncObject) &&
65+
if (_sharedLocks.TryGetValue(dataSource, out var syncObject) &&
6566
Interlocked.Decrement(ref syncObject.ReferenceCount) <= 0)
6667
{
67-
_sharedLocks.Remove(connectionString);
68+
_sharedLocks.Remove(dataSource);
6869
syncObject.Dispose();
6970
return true;
7071
}

src/System/Data/SQLite/SQLiteDbTransaction.cs

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ public sealed class SQLiteDbTransaction : Disposable, IDbTransaction
1414
private const int ROLLBACK = 2;
1515
#endregion
1616

17-
private SQLiteDbConnection? _connection;
18-
private SQLiteTransaction? _transaction;
19-
private Action? _onDispose;
17+
private readonly SQLiteDbConnection _connection;
18+
private readonly SQLiteTransaction _transaction;
2019

2120
private int _state = NONE;
2221

@@ -29,13 +28,12 @@ public sealed class SQLiteDbTransaction : Disposable, IDbTransaction
2928
/// </summary>
3029
/// <param name="connection">The SQLite database connection.</param>
3130
/// <param name="transaction">The underlying SQLite transaction.</param>
32-
/// <param name="onDispose">An action to perform upon disposal.</param>
3331
/// <exception cref="ArgumentNullException">Thrown when the provided connection or transaction is null.</exception>
34-
internal SQLiteDbTransaction(SQLiteDbConnection connection, SQLiteTransaction transaction, Action? onDispose)
32+
internal SQLiteDbTransaction(SQLiteDbConnection connection, SQLiteTransaction transaction)
3533
{
3634
_connection = connection ?? throw new ArgumentNullException(nameof(connection));
3735
_transaction = transaction ?? throw new ArgumentNullException(nameof(transaction));
38-
_onDispose = onDispose;
36+
Interlocked.Increment(ref _connection.TransactionCount);
3937
Debug.Assert(connection.DefaultTimeout == 30);
4038
}
4139

@@ -44,12 +42,12 @@ internal SQLiteDbTransaction(SQLiteDbConnection connection, SQLiteTransaction tr
4442
/// <summary>
4543
/// Gets the database connection associated with this transaction.
4644
/// </summary>
47-
public IDbConnection Connection => _transaction!.Connection;
45+
public IDbConnection Connection => _transaction.Connection;
4846

4947
/// <summary>
5048
/// Gets the isolation level of this transaction.
5149
/// </summary>
52-
public IsolationLevel IsolationLevel => _transaction!.IsolationLevel;
50+
public IsolationLevel IsolationLevel => _transaction.IsolationLevel;
5351

5452
#endregion
5553

@@ -79,32 +77,30 @@ public void Commit()
7977
{
8078
CheckDisposed();
8179
var originalState = Interlocked.CompareExchange(ref _state, COMMIT, NONE);
82-
if (originalState != NONE)
83-
{
84-
Debug.Assert(false, $"Trying commit with state: {originalState}");
85-
return;
86-
}
87-
_transaction!.Commit();
80+
Debug.Assert(originalState == NONE, $"Trying commit with state: {originalState}");
81+
Throw.InvalidOperationExceptionIf(originalState != NONE, $"Trying commit with state: {originalState}");
82+
_transaction.Commit();
8883
}
8984

9085
/// <summary>
9186
/// Disposes the resources used by this transaction.
9287
/// </summary>
9388
protected override void OnDispose()
9489
{
95-
DisposeAndNull(ref _transaction);
96-
if (_onDispose != null)
90+
try
9791
{
98-
_onDispose();
99-
_onDispose = null;
92+
_transaction.Dispose();
10093
}
94+
finally
95+
{
96+
Interlocked.Decrement(ref _connection.TransactionCount);
10197
#if DEBUG
102-
var elapsed = _watch.Elapsed;
103-
var timeout = _connection?.DefaultTimeout;
104-
Debug.Assert(elapsed.TotalSeconds < timeout, $"Transaction elapsed: {elapsed}, Expected: {timeout} sec");
98+
var elapsed = _watch.Elapsed;
99+
var timeout = _connection.DefaultTimeout;
100+
Debug.Assert(elapsed.TotalSeconds < timeout, $"Transaction elapsed: {elapsed}, Expected: {timeout} sec");
105101
#endif
106-
_connection = null;
107-
base.OnDispose();
102+
base.OnDispose();
103+
}
108104
}
109105

110106
/// <summary>
@@ -114,15 +110,11 @@ public void Rollback()
114110
{
115111
CheckDisposed();
116112
var originalState = Interlocked.CompareExchange(ref _state, ROLLBACK, NONE);
117-
if (originalState != NONE)
118-
{
119-
Debug.Assert(false, $"Trying rollback with state: {originalState}");
120-
return;
121-
}
122-
_transaction!.Rollback();
113+
Debug.Assert(originalState == NONE, $"Trying rollback with state: {originalState}");
114+
Throw.InvalidOperationExceptionIf(originalState != NONE, $"Trying rollback with state: {originalState}");
115+
_transaction.Rollback();
123116
}
124117

125118
#endregion
126-
127119
}
128120
}

0 commit comments

Comments
 (0)