MDLSoft.DistributedLock
1.0.3
dotnet add package MDLSoft.DistributedLock --version 1.0.3
NuGet\Install-Package MDLSoft.DistributedLock -Version 1.0.3
<PackageReference Include="MDLSoft.DistributedLock" Version="1.0.3" />
<PackageVersion Include="MDLSoft.DistributedLock" Version="1.0.3" />
<PackageReference Include="MDLSoft.DistributedLock" />
paket add MDLSoft.DistributedLock --version 1.0.3
#r "nuget: MDLSoft.DistributedLock, 1.0.3"
#:package MDLSoft.DistributedLock@1.0.3
#addin nuget:?package=MDLSoft.DistributedLock&version=1.0.3
#tool nuget:?package=MDLSoft.DistributedLock&version=1.0.3
MDLSoft.DistributedLock
A high-performance, lightweight distributed lock library for SQL Server with zero external dependencies.
Features
- 🔒 Distributed Locking: Acquire and release locks across multiple processes/applications
- 🗄️ SQL Server Backend: Uses SQL Server as the lock storage mechanism
- ⚡ Zero Dependencies: Built with raw ADO.NET for maximum performance and minimal footprint
- 🔄 Sync & Async: Full support for both synchronous and asynchronous operations
- 🎯 Universal Compatibility: Single package supports .NET Framework 4.0 through .NET 8+
- 🚀 High Performance: Optimized lock acquisition with READ COMMITTED isolation
- 🔧 Simple API: Clean, intuitive interface with manual lock release
- 📦 Lightweight: Only 49KB package size
Installation
Install the package via NuGet:
# Single package for ALL .NET versions (4.0 through 8+)
dotnet add package MDLSoft.DistributedLock
Or via Package Manager Console:
# Works with any .NET version
Install-Package MDLSoft.DistributedLock
Quick Start
1. Setup the Database Table
var connectionString = "Server=.;Database=MyApp;Integrated Security=true;";
var provider = new SqlServerDistributedLockProvider(connectionString);
// Ensure the locks table exists
await provider.EnsureTableExistsAsync();
2. Basic Usage
// Synchronous usage
using (var lockProvider = new SqlServerDistributedLockProvider(connectionString))
{
using (var distributedLock = lockProvider.TryAcquireLock("my-resource"))
{
if (distributedLock != null)
{
// Critical section - only one process can execute this
Console.WriteLine("Lock acquired successfully!");
// Do your work here...
}
else
{
Console.WriteLine("Could not acquire lock");
}
} // Lock is automatically released here
}
// Asynchronous usage
using (var lockProvider = new SqlServerDistributedLockProvider(connectionString))
{
using (var distributedLock = await lockProvider.TryAcquireLockAsync("my-resource"))
{
if (distributedLock != null)
{
// Critical section
await DoImportantWorkAsync();
}
}
}
3. Advanced Usage
var lockProvider = new SqlServerDistributedLockProvider(connectionString);
try
{
// Acquire lock with timeout
using (var distributedLock = await lockProvider.AcquireLockAsync(
lockId: "critical-operation",
timeout: TimeSpan.FromSeconds(30)))
{
// Your critical work here
await ProcessLongRunningOperationAsync();
// Manual release (optional - automatic on dispose)
await distributedLock.ReleaseAsync();
}
}
catch (DistributedLockTimeoutException ex)
{
Console.WriteLine($"Could not acquire lock '{ex.LockId}' within the specified timeout");
}
Examples
Complete Example Applications
This repository includes comprehensive example applications demonstrating various usage patterns:
1. Modern .NET Example (MDLSoft.DistributedLock.Example
)
- Target: .NET 8 (modern applications)
- Features: Async/await, cancellation tokens, modern C# patterns
- Use Case: Web applications, services, modern desktop apps
2. .NET Framework 4.0 Example (MDLSoft.DistributedLock.Example.Net40
)
- Target: .NET Framework 4.0 (legacy compatibility)
- Features: Synchronous operations, classic .NET patterns, Thread-based concurrency
- Use Case: Legacy applications, Windows services, older codebases
What the examples demonstrate:
- ✅ Basic lock acquisition and release patterns
- ✅ Lock timeout handling and conflict resolution
- ✅ Concurrent access simulation (multiple threads/processes)
- ✅ Proper error handling and exception management
- ✅ IDisposable pattern for automatic cleanup
- ✅ Configuration management (app.config/appsettings.json)
- ✅ Database table initialization
- ✅ Thread safety and synchronization patterns
Running the examples:
# Modern .NET example
cd MDLSoft.DistributedLock.Example
dotnet run
# .NET Framework 4.0 example (requires Visual Studio or MSBuild)
cd MDLSoft.DistributedLock.Example.Net40
# Build with Visual Studio or MSBuild, then run the .exe
API Reference
IDistributedLockProvider
The main interface for acquiring distributed locks.
Methods
TryAcquireLock(string lockId, TimeSpan? timeout = null)
- Attempts to acquire a lock synchronouslyTryAcquireLockAsync(string lockId, TimeSpan? timeout = null, CancellationToken cancellationToken = default)
- Attempts to acquire a lock asynchronouslyAcquireLock(string lockId, TimeSpan? timeout = null)
- Acquires a lock synchronously (throws on failure)AcquireLockAsync(string lockId, TimeSpan? timeout = null, CancellationToken cancellationToken = default)
- Acquires a lock asynchronously (throws on failure)
IDistributedLock
Represents an acquired distributed lock.
Properties
string LockId
- The unique identifier for the lockbool IsAcquired
- Whether the lock is currently acquired
Methods
Release()
- Releases the lock synchronouslyReleaseAsync(CancellationToken cancellationToken = default)
- Releases the lock asynchronously
SqlServerDistributedLockProvider
SQL Server implementation of the distributed lock provider.
Constructor
public SqlServerDistributedLockProvider(string connectionString, string tableName = "DistributedLocks")
Additional Methods
EnsureTableExists()
- Creates the locks table if it doesn't exist (sync)EnsureTableExistsAsync(CancellationToken cancellationToken = default)
- Creates the locks table if it doesn't exist (async)
Database Schema
The library automatically creates the following table structure:
CREATE TABLE [DistributedLocks] (
[LockId] NVARCHAR(255) NOT NULL PRIMARY KEY,
[LockToken] NVARCHAR(255) NOT NULL,
[CreatedAt] DATETIME2 NOT NULL DEFAULT GETUTCDATE()
);
Configuration
Connection Strings
The library supports:
- System.Data.SqlClient (for .NET Framework 4.0-4.8)
- Microsoft.Data.SqlClient (for .NET Standard 2.0/.NET Core/.NET 5+)
Custom Table Name
You can specify a custom table name for the locks:
var provider = new SqlServerDistributedLockProvider(connectionString, "MyCustomLocksTable");
Error Handling
The library includes specific exception types:
DistributedLockException
- Base exception for all lock operationsDistributedLockTimeoutException
- Thrown when a lock cannot be acquired within the timeout periodDistributedLockOperationException
- Thrown when a lock operation fails
Best Practices
- Always use
using
statements to ensure locks are properly released - Use timeouts when acquiring locks to avoid indefinite waiting
- Handle timeout exceptions gracefully in your application
- Monitor lock duration - Keep critical sections as short as possible
- Use meaningful lock IDs that clearly identify the resource being protected
Performance Considerations
- Lightweight: Zero external dependencies (except minimal framework backports)
- Fast: Raw ADO.NET operations with optimized SQL
- Efficient: Lock acquisition uses READ COMMITTED isolation with primary key constraints
- Scalable: Consider the database load when using many concurrent locks
Thread Safety
The library is thread-safe and can be used from multiple threads simultaneously. Each lock acquisition creates a unique lock token to prevent conflicts.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
If you encounter any issues or have questions, please open an issue on GitHub.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net40 is compatible. net403 was computed. net45 was computed. net451 is compatible. net452 was computed. net46 was computed. net461 is compatible. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 is compatible. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.0
- Microsoft.Bcl.Async (>= 1.0.168)
-
.NETFramework 4.5.1
- Microsoft.Bcl.Async (>= 1.0.168)
-
.NETFramework 4.6.1
- No dependencies.
-
.NETFramework 4.8
- No dependencies.
-
.NETStandard 2.0
- Microsoft.Data.SqlClient (>= 6.1.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.