Skip to content

Commit e5ddde6

Browse files
adding XML documentation
1 parent aa95637 commit e5ddde6

10 files changed

Lines changed: 351 additions & 264 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ Sqlite-Concurrency/obj/
66
.idea/
77

88
EntityFrameworkCore.Sqlite.Concurrency/obj/
9+
10+
EntityFrameworkCore.Sqlite.Concurrency/bin/

EntityFrameworkCore.Sqlite.Concurrency/EFCore.Sqlite.Concurrency.csproj

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,20 @@ Get started in one line. Stop compromising on SQLite reliability and speed.
6969
<!-- Licensing & Documentation (Mandatory for Trust) -->
7070
<PackageLicenseExpression>MIT</PackageLicenseExpression>
7171
<PackageReadmeFile>README.md</PackageReadmeFile>
72-
<PackageIcon>res\logo.png</PackageIcon>
72+
<PackageIcon>logo.png</PackageIcon>
7373
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
7474

7575
<!-- Build & Packaging Configuration -->
7676
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
7777
<IsPackable>true</IsPackable>
78+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
7879

7980
<!-- Debug Symbol Configuration -->
8081
<IncludeSymbols>true</IncludeSymbols>
8182
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
83+
84+
<!-- Deterministic Builds for CI -->
85+
<ContinuousIntegrationBuild Condition="'$(GITHUB_ACTIONS)' == 'true'">true</ContinuousIntegrationBuild>
8286
</PropertyGroup>
8387

8488
<!-- Dependencies -->
@@ -87,7 +91,6 @@ Get started in one line. Stop compromising on SQLite reliability and speed.
8791
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.0" />
8892
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0" />
8993
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
90-
<PackageReference Include="System.Threading.Channels" Version="8.0.0" />
9194
<!-- SourceLink for debugging support -->
9295
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
9396
</ItemGroup>
@@ -101,6 +104,6 @@ Get started in one line. Stop compromising on SQLite reliability and speed.
101104
<!-- Packaged Files -->
102105
<ItemGroup>
103106
<None Include="..\README.md" Pack="true" PackagePath="\" />
104-
<None Include="res\logo.png" Pack="true" PackagePath="res\" />
107+
<None Include="res\logo.png" Pack="true" PackagePath="\" />
105108
</ItemGroup>
106109
</Project>

EntityFrameworkCore.Sqlite.Concurrency/src/ExtensionMethods/SqliteConcurrencyServiceCollectionExtensions.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,20 @@
44

55
namespace EntityFrameworkCore.Sqlite.Concurrency.ExtensionMethods;
66

7+
/// <summary>
8+
/// Extension methods for IServiceCollection to add concurrent SQLite DbContexts.
9+
/// </summary>
710
public static class SqliteConcurrencyServiceCollectionExtensions
811
{
12+
/// <summary>
13+
/// Adds a DbContext configured with optimized SQLite concurrency and performance settings.
14+
/// </summary>
15+
/// <typeparam name="TContext">The type of the DbContext.</typeparam>
16+
/// <param name="services">The service collection.</param>
17+
/// <param name="connectionString">The SQLite connection string.</param>
18+
/// <param name="configure">An optional action to configure concurrency options.</param>
19+
/// <param name="contextLifetime">The lifetime of the DbContext.</param>
20+
/// <returns>The service collection.</returns>
921
public static IServiceCollection AddConcurrentSqliteDbContext<TContext>(
1022
this IServiceCollection services,
1123
string connectionString,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,27 @@
11
namespace EntityFrameworkCore.Sqlite.Concurrency.Models;
22

3+
/// <summary>
4+
/// Options for configuring SQLite concurrency and performance.
5+
/// </summary>
36
public class SqliteConcurrencyOptions
47
{
8+
/// <summary>
9+
/// The maximum number of retry attempts for SQLITE_BUSY errors.
10+
/// </summary>
511
public int MaxRetryAttempts { get; set; } = 3;
12+
13+
/// <summary>
14+
/// The busy timeout for SQLite connections.
15+
/// </summary>
616
public TimeSpan BusyTimeout { get; set; } = TimeSpan.FromSeconds(30);
17+
18+
/// <summary>
19+
/// The command timeout for SQLite commands.
20+
/// </summary>
721
public int CommandTimeout { get; set; } = 300; // 5 minutes
22+
23+
/// <summary>
24+
/// The number of pages for WAL auto-checkpoint.
25+
/// </summary>
826
public int WalAutoCheckpoint { get; set; } = 1000;
927
}

EntityFrameworkCore.Sqlite.Concurrency/src/SqliteConcurrencyExtensions.cs

Lines changed: 50 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -6,60 +6,55 @@
66

77
namespace EntityFrameworkCore.Sqlite.Concurrency;
88

9+
/// <summary>
10+
/// Extension methods for configuring SQLite concurrency and performance in EF Core.
11+
/// </summary>
912
public static class SqliteConcurrencyExtensions
1013
{
11-
public static DbContextOptionsBuilder UseSqliteWithConcurrency(
12-
this DbContextOptionsBuilder optionsBuilder,
13-
string connectionString,
14-
Action<SqliteConcurrencyOptions>? configure = null)
15-
{
16-
var options = new SqliteConcurrencyOptions();
17-
configure?.Invoke(options);
18-
19-
// Get the enhanced connection string
20-
var enhancedConnectionString = SqliteConnectionEnhancer
21-
.GetOptimizedConnectionString(connectionString);
22-
23-
// Create a configured connection
24-
var connection = new SqliteConnection(enhancedConnectionString);
25-
26-
// Apply optimizations when connection opens
27-
connection.StateChange += (sender, args) =>
28-
{
29-
if (args.OriginalState == ConnectionState.Closed &&
30-
args.CurrentState == ConnectionState.Open)
31-
{
32-
if (sender is SqliteConnection sqliteConnection)
33-
{
34-
// Apply runtime pragmas
35-
SqliteConnectionEnhancer.ApplyRuntimePragmas(sqliteConnection, options);
36-
37-
// Set busy timeout
38-
SetBusyTimeout(sqliteConnection, options.BusyTimeout);
39-
40-
// Additional optimizations
41-
ConfigureForWriteQueue(sqliteConnection);
42-
SetWalCheckpoint(sqliteConnection, options.WalAutoCheckpoint);
43-
}
44-
}
45-
};
14+
/// <summary>
15+
/// Configures the context to use SQLite with optimized concurrency and performance settings.
16+
/// </summary>
17+
/// <param name="optionsBuilder">The options builder.</param>
18+
/// <param name="connectionString">The SQLite connection string.</param>
19+
/// <param name="configure">An optional action to configure concurrency options.</param>
20+
/// <returns>The options builder.</returns>
21+
public static DbContextOptionsBuilder UseSqliteWithConcurrency(
22+
this DbContextOptionsBuilder optionsBuilder,
23+
string connectionString,
24+
Action<SqliteConcurrencyOptions>? configure = null)
25+
{
26+
var options = new SqliteConcurrencyOptions();
27+
configure?.Invoke(options);
4628

47-
// Use the configured connection with EF Core
48-
optionsBuilder.UseSqlite(connection, sqliteOptions =>
49-
{
50-
// Configure command timeout
51-
sqliteOptions.CommandTimeout(options.CommandTimeout);
52-
});
53-
54-
// Always add interceptors for write queue
55-
var interceptor = SqliteConnectionEnhancer.GetInterceptor(enhancedConnectionString, options);
56-
optionsBuilder.AddInterceptors(interceptor);
57-
58-
return optionsBuilder;
59-
}
29+
// Get the enhanced connection string
30+
var enhancedConnectionString = SqliteConnectionEnhancer
31+
.GetOptimizedConnectionString(connectionString);
32+
33+
// Use the connection string with EF Core to allow proper pooling
34+
optionsBuilder.UseSqlite(enhancedConnectionString, sqliteOptions =>
35+
{
36+
// Configure command timeout
37+
sqliteOptions.CommandTimeout(options.CommandTimeout);
38+
});
39+
40+
// Add interceptors for PRAGMAs, performance, and concurrency
41+
var interceptor = SqliteConnectionEnhancer.GetInterceptor(enhancedConnectionString, options);
42+
optionsBuilder.AddInterceptors(interceptor);
43+
44+
return optionsBuilder;
45+
}
6046

6147

6248

49+
/// <summary>
50+
/// Executes an operation with automatic retry on SQLITE_BUSY errors.
51+
/// </summary>
52+
/// <typeparam name="T">The result type.</typeparam>
53+
/// <param name="context">The database context.</param>
54+
/// <param name="operation">The operation to execute.</param>
55+
/// <param name="maxRetries">The maximum number of retries.</param>
56+
/// <param name="cancellationToken">The cancellation token.</param>
57+
/// <returns>The result of the operation.</returns>
6358
public static async Task<T> ExecuteWithRetryAsync<T>(
6459
this DbContext context,
6560
Func<DbContext, Task<T>> operation,
@@ -81,6 +76,13 @@ public static async Task<T> ExecuteWithRetryAsync<T>(
8176
}
8277
}
8378

79+
/// <summary>
80+
/// Performs a bulk insert with optimized settings and optional app-level locking.
81+
/// </summary>
82+
/// <typeparam name="T">The entity type.</typeparam>
83+
/// <param name="context">The database context.</param>
84+
/// <param name="entities">The entities to insert.</param>
85+
/// <param name="cancellationToken">The cancellation token.</param>
8486
public static async Task BulkInsertOptimizedAsync<T>(
8587
this DbContext context,
8688
IEnumerable<T> entities,
@@ -122,28 +124,4 @@ public static async Task BulkInsertOptimizedAsync<T>(
122124
writeLock.Release();
123125
}
124126
}
125-
126-
private static void ConfigureForWriteQueue(SqliteConnection connection)
127-
{
128-
using var command = connection.CreateCommand();
129-
command.CommandText = @"
130-
PRAGMA cache_size = -2000;
131-
PRAGMA page_size = 4096;
132-
";
133-
command.ExecuteNonQuery();
134-
}
135-
136-
private static void SetBusyTimeout(SqliteConnection connection, TimeSpan timeout)
137-
{
138-
using var command = connection.CreateCommand();
139-
command.CommandText = $"PRAGMA busy_timeout = {(int)timeout.TotalMilliseconds};";
140-
command.ExecuteNonQuery();
141-
}
142-
143-
private static void SetWalCheckpoint(SqliteConnection connection, int checkpointPages)
144-
{
145-
using var command = connection.CreateCommand();
146-
command.CommandText = $"PRAGMA wal_autocheckpoint = {checkpointPages};";
147-
command.ExecuteNonQuery();
148-
}
149127
}

0 commit comments

Comments
 (0)