Skip to content

Commit 51af0c5

Browse files
committed
Readme updates for improved description as Mutex capability and multiple Nuget Packages, etc.
1 parent 0c1f00a commit 51af0c5

1 file changed

Lines changed: 24 additions & 16 deletions

File tree

README.md

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# SqlAppLockHelper
2-
A very lightweight library that provides and easy to use API for the Sql Server Application Lock Stored Procs
3-
(e.g. sp_getapplock & sp_releaseapplock). These stored procs provide a robust & efficient distributed locking
4-
capability using Sql Server. And this library exposes this in an easy to use API using custom extension methods
5-
on the SqlConnection and SqlTransaction classes of the existing SqlClient.
1+
# SqlAppLockHelper -- Easy Distributed Mutex/Locking with Sql Server
2+
An ultra lightweight library that provides and easy to use API for a robust distributed mutex locking capability that leverages
3+
Sql Server (e.g. sp_getapplock & sp_releaseapplock). Sql Server provides a very robust & efficient distributed mutex/locking
4+
capability and this library exposes this in an easy to use C# .Net Standard API using custom extension methods
5+
on the SqlConnection and SqlTransaction classes of the SqlClient libraries.
66

77
#### SqlClient Namespaces:
88
There are two namespaces for SqlClient, and this library supports both:
@@ -20,10 +20,13 @@ There are two scopes for Locks that are supported:
2020

2121
#### Usage Notes:
2222
- The generally recommended approach is to use the *Transaction* scope because it is slightly safer (e.g. more resilient agains
23-
abandoned locks).
24-
- The LockTimeout value is the value for which Sql Server will try and wait for Lock Acquisition. By specifying Zero
23+
abandoned locks) by allowing the Locks to automatically expire with the Transaction; and is the default behavior of Sql Server.
24+
- However the *Session* scope is reliably implemented via IDisposable/IAsyncDisposable C# interfaces leaving
25+
the main residual risk of Database communication or Network issues, whereby if we can't communicate with the DB then we can't explicity release the lock.
26+
- The lock _acquisition timeout_ value is the value (in seconds) for which Sql Server will try and wait for Lock Acquisition. By specifying Zero
2527
(0 seconds) then Sql Server will attempt to get the lock but immediately fail lock acquisition and return if it cannot
2628
acquire the lock.
29+
- All locks are acquired as Exclusive locks for true _distributed mutex_ functionality.
2730
- More info can be found here:
2831
- [sp_getapplock](https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-getapplock-transact-sql?view=sql-server-ver15)
2932
- [sp_releaseapplock](https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-releaseapplock-transact-sql?view=sql-server-ver15)
@@ -37,11 +40,13 @@ Queue Processing logic, Transactional Outbox Pattern, etc.).
3740

3841

3942
## Nuget Package
40-
To use in your project, add the [SqlAppLockHelper NuGet package](https://www.nuget.org/packages/SqlAppLockHelper/) to your project.
43+
To use in your project, add the appropriate package to your project for the namespace you are using:
44+
- [SqlAppLockHelper.MicrosoftData NuGet package](https://www.nuget.org/packages/SqlAppLockHelper.MicrosoftData/)
45+
- [SqlAppLockHelper.SystemData NuGet package](https://www.nuget.org/packages/SqlAppLockHelper.SystemData/)
4146

4247
## Usage:
4348

44-
### Import the Custom Extensions:
49+
#### Import the Custom Extensions:
4550
First import the extensions for the library you are using:
4651
```csharp
4752
using Microsoft.Data.SqlClient;
@@ -54,7 +59,10 @@ using SqlAppLockHelper.SystemDataNS;
5459
```
5560

5661
### Simple Example:
57-
Usage is very simple by using custom extensions of the SqlConnection or SqlTransaction.
62+
Usage is very simple by using custom extensions of the SqlConnection or SqlTransaction. The following example shows
63+
the recommended usage of Transaction Scope by calling `.AcquireAppLockAsync(...)` on the SqlTransaction instance:
64+
65+
*NOTE:* Async is recommended, but the sync implementation works exactly the same -- sans async/await.
5866

5967
#### Using Sql Transaction (Transaction Scope will be used):
6068
```csharp
@@ -64,10 +72,10 @@ Usage is very simple by using custom extensions of the SqlConnection or SqlTrans
6472
await using var sqlTrans = (SqlTransaction)await sqlConn.BeginTransactionAsync();
6573

6674
//Using any SqlTransaction (cast DbTransaction to SqlTransaction if needed), this will
67-
// attempt to acquire a distributed lock, and will wait up to 5 seconds before timing out.
75+
// attempt to acquire a distributed mutex/lock, and will wait up to 5 seconds before timing out.
6876
//Note: Default behavior is to throw and exception if the Lock cannot be acquired
69-
// (e.g. is already held by another process) but this can be overridden by parameter
70-
// to return the state in the appLock result.
77+
// (e.g. is already held by another process) but this can be overridden by parameter
78+
// to return the state in the appLock result.
7179
await using var appLock = await sqlTrans.AcquireAppLockAsync("MyAppBulkLoadingDistributedLock", 5);
7280

7381
if(appLock.IsAcquired)
@@ -83,10 +91,10 @@ _*NOTE: *Application Lock should ALWAYS be explicity Disposed of to ensure Lock
8391
await sqlConn.OpenAsync();
8492

8593
//Using any SqlTransaction (cast DbTransaction to SqlTransaction if needed), this will
86-
// attempt to acquire a distributed lock, and will wait up to 5 seconds before timing out.
94+
// attempt to acquire a distributed mutex/lock, and will wait up to 5 seconds before timing out.
8795
//Note: Default behavior is to throw and exception if the Lock cannot be acquired
88-
// (e.g. is already held by another process) but this can be overridden by parameter
89-
// to return the state in the appLock result.
96+
// (e.g. is already held by another process) but this can be overridden by parameter
97+
// to return the state in the appLock result.
9098
//Note: The IDisposable/IAsyncDisposable implementation ensures that the Lock is released!
9199
await using var appLock = await sqlConn.AcquireAppLockAsync("MyAppBulkLoadingDistributedLock", 5);
92100

0 commit comments

Comments
 (0)