### Install SqliteWasmBlazor Package Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/README.md Commands to install the SqliteWasmBlazor NuGet package or build from source. ```bash dotnet add package SqliteWasmBlazor --prerelease dotnet add package SqliteWasmBlazor --version 0.6.5-pre git clone https://github.com/bernisoft/SqliteWasmBlazor.git cd SqliteWasmBlazor dotnet build ``` -------------------------------- ### Setup for Non-EF Core Usage Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/ado-net.md Demonstrates how to register and initialize the SqliteWasm database management service in your Blazor WASM application for standalone ADO.NET usage. ```APIDOC ## Setup for Non-EF Core Usage ### Description Register and initialize the `SqliteWasm` database management service for standalone ADO.NET usage in your Blazor WASM application. ### Method N/A (Configuration) ### Endpoint N/A (Configuration) ### Parameters N/A ### Request Example ```csharp // Program.cs using SqliteWasmBlazor; var builder = WebAssemblyHostBuilder.CreateDefault(args); // Register SqliteWasm database management service builder.Services.AddSqliteWasm(); var host = builder.Build(); // Initialize the SqliteWasm worker bridge (no EF Core needed) await host.Services.InitializeSqliteWasmAsync(); await host.RunAsync(); ``` ### Response N/A ``` -------------------------------- ### Implement Atomic Database Import with Rollback Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/advanced-features.md This example demonstrates a safe pattern for importing database files using a rename-based backup strategy to ensure atomicity and enable rollback. It first closes the current database, renames it to a backup file, imports the new data, and then either deletes the backup upon successful validation or restores it if an error occurs. ```csharp await DatabaseService.CloseDatabaseAsync("TodoDb.db"); await DatabaseService.RenameDatabaseAsync("TodoDb.db", "TodoDb.backup.db"); await DatabaseService.ImportDatabaseAsync("TodoDb.db", data); // Validate, then either delete backup (success) or restore it (failure) ``` -------------------------------- ### Configure Per-Connection Logging Level Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/advanced-features.md C# code example showing how to specify a log level directly when creating a `SqliteWasmConnection`. This allows for granular control over logging for individual database connections. ```csharp // Specify log level in connection constructor var connection = new SqliteWasmConnection("Data Source=MyDb.db", LogLevel.Debug); ``` -------------------------------- ### Configure Multi-Database Support in Blazor Source: https://context7.com/b-straub/sqlitewasmblazor/llms.txt Demonstrates how to register multiple DbContexts and initialize them independently within a Blazor application. This setup allows for separate migration histories and database files. ```csharp builder.Services.AddDbContextFactory(options => { var connection = new SqliteWasmConnection("Data Source=TodoDb.db"); options.UseSqliteWasm(connection); }); builder.Services.AddDbContextFactory(options => { var connection = new SqliteWasmConnection("Data Source=NotesDb.db"); options.UseSqliteWasm(connection); }); builder.Services.AddSingleton(); builder.Services.AddSqliteWasm(); var host = builder.Build(); await host.Services.InitializeSqliteWasmDatabaseAsync(); await host.Services.InitializeSqliteWasmDatabaseAsync(); ``` ```csharp @inject IDbContextFactory TodoFactory @inject IDbContextFactory NoteFactory @code { private async Task LoadDataFromBothDatabases() { await using var todoCtx = await TodoFactory.CreateDbContextAsync(); var todos = await todoCtx.TodoItems.ToListAsync(); await using var noteCtx = await NoteFactory.CreateDbContextAsync(); var notes = await noteCtx.Notes.ToListAsync(); } private async Task LinkNoteToTodo(Guid noteId, Guid todoId) { await using var noteCtx = await NoteFactory.CreateDbContextAsync(); var note = await noteCtx.Notes.FindAsync(noteId); if (note is not null) { note.LinkedTodoId = todoId; await noteCtx.SaveChangesAsync(); } } } ``` -------------------------------- ### Perform Database Management with ISqliteWasmDatabaseService Source: https://context7.com/b-straub/sqlitewasmblazor/llms.txt Provides examples for low-level database management tasks including checking existence, resetting, renaming, and performing atomic import/export operations on SQLite files in OPFS. ```csharp @inject ISqliteWasmDatabaseService DatabaseService @inject IDbContextFactory DbFactory @code { private async Task CheckDatabaseExists() { return await DatabaseService.ExistsDatabaseAsync("TodoDb.db"); } private async Task ResetDatabaseAsync() { await DatabaseService.DeleteDatabaseAsync("TodoDb.db"); await using var context = await DbFactory.CreateDbContextAsync(); await context.Database.MigrateAsync(); } private async Task BackupDatabaseAsync() { await DatabaseService.CloseDatabaseAsync("TodoDb.db"); await DatabaseService.RenameDatabaseAsync("TodoDb.db", "TodoDb.backup.db"); } private async Task ExportDatabaseAsync() { byte[] data = await DatabaseService.ExportDatabaseAsync("TodoDb.db"); return data; } private async Task ImportDatabaseAsync(byte[] data) { await DatabaseService.CloseDatabaseAsync("TodoDb.db"); await DatabaseService.RenameDatabaseAsync("TodoDb.db", "TodoDb.backup.db"); try { await DatabaseService.ImportDatabaseAsync("TodoDb.db", data); await using var ctx = await DbFactory.CreateDbContextAsync(); await ctx.ValidateImportedSchemaAsync("TodoDb.db"); await DatabaseService.DeleteDatabaseAsync("TodoDb.backup.db"); } catch (InvalidOperationException) { await DatabaseService.DeleteDatabaseAsync("TodoDb.db"); await DatabaseService.RenameDatabaseAsync("TodoDb.backup.db", "TodoDb.db"); throw; } } } ``` -------------------------------- ### Setup EF Core Migrations for WASM Source: https://context7.com/b-straub/sqlitewasmblazor/llms.txt Configures a design-time factory to allow migration generation in a WebAssembly project. Includes XML configuration for NuGet packages and CLI commands for migration generation. ```xml runtime; analyzers; all ``` ```csharp public class TodoDbContextFactory : IDesignTimeDbContextFactory { public TodoDbContext CreateDbContext(string[] args) { var optionsBuilder = new DbContextOptionsBuilder(); optionsBuilder.UseSqlite("Data Source=:memory:"); return new TodoDbContext(optionsBuilder.Options); } } ``` ```bash dotnet ef migrations add InitialCreate --context TodoDbContext --output-dir Migrations ``` -------------------------------- ### EF Core Migrations Setup Source: https://context7.com/b-straub/sqlitewasmblazor/llms.txt Configure Entity Framework Core migrations for SqliteWasmBlazor projects, using a separate models project to prevent design-time asset conflicts in WebAssembly. ```APIDOC ## EF Core Migrations Setup Configure migrations for SqliteWasmBlazor with a separate models project to avoid design-time asset conflicts in WebAssembly. ### YourApp.Models.csproj ```xml runtime; analyzers; all ``` ### Design-time Factory for Migration Generation ```csharp // Design-time factory for migration generation public class TodoDbContextFactory : IDesignTimeDbContextFactory { public TodoDbContext CreateDbContext(string[] args) { var optionsBuilder = new DbContextOptionsBuilder(); optionsBuilder.UseSqlite("Data Source=:memory:"); return new TodoDbContext(optionsBuilder.Options); } } ``` ### Generating Migrations ```bash # Generate migrations dotnet ef migrations add InitialCreate --context TodoDbContext --output-dir Migrations # For multiple contexts, use separate folders dotnet ef migrations add InitialCreate --context NoteDbContext --output-dir NoteMigrations ``` ``` -------------------------------- ### Using Transactions with SqliteWasmBlazor Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/ado-net.md Illustrates how to manage database transactions using SqliteWasmBlazor. This includes starting a transaction, executing multiple commands within that transaction, and committing or rolling back the transaction based on success or failure, ensuring data integrity. ```csharp await using var connection = new SqliteWasmConnection("Data Source=MyApp.db"); await connection.OpenAsync(); // Start transaction await using var transaction = await connection.BeginTransactionAsync(); try { // Execute multiple commands await using var cmd1 = connection.CreateCommand(); cmd1.Transaction = transaction; cmd1.CommandText = "INSERT INTO Users (Name, Email) VALUES ('Alice', 'alice@example.com')"; await cmd1.ExecuteNonQueryAsync(); await using var cmd2 = connection.CreateCommand(); cmd2.Transaction = transaction; cmd2.CommandText = "UPDATE Users SET Email = 'newemail@example.com' WHERE Name = 'Bob'"; await cmd2.ExecuteNonQueryAsync(); // Commit transaction await transaction.CommitAsync(); } catch { // Rollback on error await transaction.RollbackAsync(); throw; } ``` -------------------------------- ### Setup SqliteWasmBlazor for Non-EF Core Usage Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/ado-net.md Configures the Blazor WASM host to use SqliteWasmBlazor's ADO.NET provider. This involves registering the service and initializing the worker bridge, enabling direct database access without Entity Framework Core overhead. ```csharp using SqliteWasmBlazor; var builder = WebAssemblyHostBuilder.CreateDefault(args); // Register SqliteWasm database management service builder.Services.AddSqliteWasm(); var host = builder.Build(); // Initialize the SqliteWasm worker bridge (no EF Core needed) await host.Services.InitializeSqliteWasmAsync(); await host.RunAsync(); ``` -------------------------------- ### Initialize SqliteWasm for ADO.NET in Program.cs Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/SqliteWasmBlazor.AdoNetSample/README.md Initializes SqliteWasm for direct ADO.NET usage within a Blazor application. This setup bypasses the need for Entity Framework Core, enabling direct interaction with SQLite through ADO.NET APIs. It requires the host services to be configured for this initialization. ```csharp await host.Services.InitializeSqliteWasmAsync(); ``` -------------------------------- ### Setup SqliteWasm Blazor for ADO.NET Only Source: https://context7.com/b-straub/sqlitewasmblazor/llms.txt Configures a Blazor WebAssembly application to use SqliteWasm with the ADO.NET provider, bypassing EF Core for direct database interactions. This is ideal for lightweight applications or migrating existing ADO.NET code. ```csharp using SqliteWasmBlazor; var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.Services.AddSqliteWasm(); var host = builder.Build(); // Initialize worker bridge without EF Core await host.Services.InitializeSqliteWasmAsync(); await host.RunAsync(); ``` -------------------------------- ### Perform Decimal Arithmetic with EF Core Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/advanced-features.md This example shows how EF Core automatically translates decimal arithmetic operations into appropriate SQLite functions, ensuring accurate calculations even though SQLite lacks native decimal support. It uses a LINQ query to filter products based on a price calculation. ```csharp var expensive = await dbContext.Products .Where(p => p.Price * 1.2m > 100m) .ToListAsync(); ``` -------------------------------- ### Run Sample Application Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/SqliteWasmBlazor.AdoNetSample/README.md Command to navigate to the sample's directory and run the application. This typically involves changing the current directory and executing the .NET run command. After execution, the application can be accessed via a local development server. ```bash cd SqliteWasmBlazor.AdoNetSample dotnet run ``` -------------------------------- ### Define Entity Framework DbContext Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/README.md Example of defining a standard EF Core DbContext for use with the SqliteWasm provider. ```csharp public class TodoDbContext : DbContext { public TodoDbContext(DbContextOptions options) : base(options) { } public DbSet TodoItems { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity(entity => { entity.HasKey(e => e.Id); entity.Property(e => e.Title).IsRequired().HasMaxLength(200); }); } } public class TodoItem { public int Id { get; set; } public string Title { get; set; } public bool IsCompleted { get; set; } public DateTime CreatedAt { get; set; } } ``` -------------------------------- ### Perform Data Initialization Without Page Reloads Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/patterns.md Shows the correct pattern for fetching remote data and populating a local SQLite database on startup, avoiding the race conditions caused by full page reloads in OPFS-backed applications. ```csharp protected override async Task OnInitializedAsync() { await using var context = await DbContextFactory.CreateDbContextAsync(); var hasData = await context.TodoItems.AnyAsync(); if (!hasData) { var remoteData = await HttpClient.GetFromJsonAsync>("api/todos"); if (remoteData is not null) { foreach (var dto in remoteData) { context.TodoItems.Add(dto.ToEntity()); } await context.SaveChangesAsync(); } } _todos = await context.TodoItems.OrderBy(t => t.UpdatedAt).ToListAsync(); } ``` -------------------------------- ### Implement Loose Cross-Database References Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/multi-database.md Use GUIDs to link entities across independent databases without enforcing database-level foreign key constraints. ```csharp public class Note { [Key] public Guid Id { get; set; } public required string Title { get; set; } public required string Content { get; set; } public Guid? TodoId { get; set; } } ``` -------------------------------- ### Manage Database via ISqliteWasmDatabaseService Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/CHANGELOG.md Demonstrates how to inject the database service and perform operations like deleting a database. ```csharp @inject ISqliteWasmDatabaseService DatabaseService // Delete a database await DatabaseService.DeleteDatabaseAsync("MyDb.db"); ``` -------------------------------- ### Implement Safe Import with Backup Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/CHANGELOG.md A robust pattern for importing databases by creating a temporary backup, validating the new file, and rolling back if validation fails. ```csharp await DatabaseService.CloseDatabaseAsync("TodoDb.db"); await DatabaseService.RenameDatabaseAsync("TodoDb.db", "TodoDb.backup.db"); try { await DatabaseService.ImportDatabaseAsync("TodoDb.db", data); await using var ctx = await DbContextFactory.CreateDbContextAsync(); await ctx.ValidateSchemaAsync(); await DatabaseService.DeleteDatabaseAsync("TodoDb.backup.db"); } catch (InvalidOperationException) { await DatabaseService.DeleteDatabaseAsync("TodoDb.db"); await DatabaseService.RenameDatabaseAsync("TodoDb.backup.db", "TodoDb.db"); throw; } ``` -------------------------------- ### Safe Import with Backup/Restore Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/CHANGELOG.md Demonstrates a pattern for safely importing a new database file by backing up the existing one and restoring it if the import fails. ```APIDOC ## Safe Import with Backup/Restore ### Description Implements a robust import process that includes backing up the current database before importing a new one, and automatically restoring the backup if the new import fails schema validation. ### Method Sequence of `ISqliteWasmDatabaseService` operations and schema validation. ### Endpoint N/A (Conceptual pattern using service methods) ### Parameters - **data** (byte[]) - Required - The raw byte data of the new database file to import. ### Request Example ```csharp // Assume 'data' contains the new database file bytes // 1. Backup existing database await DatabaseService.CloseDatabaseAsync("TodoDb.db"); await DatabaseService.RenameDatabaseAsync("TodoDb.db", "TodoDb.backup.db"); // 2. Import new file try { await DatabaseService.ImportDatabaseAsync("TodoDb.db", data); // 3. Validate schema await using var ctx = await DbContextFactory.CreateDbContextAsync(); await ctx.ValidateSchemaAsync(); // 4. Success — delete backup await DatabaseService.DeleteDatabaseAsync("TodoDb.backup.db"); } catch (InvalidOperationException) { // 5. Failed — restore from backup await DatabaseService.DeleteDatabaseAsync("TodoDb.db"); await DatabaseService.RenameDatabaseAsync("TodoDb.backup.db", "TodoDb.db"); throw; // Re-throw the exception after restoring } ``` ### Response - **Success**: The new database is imported and validated; the backup is deleted. - **Failure**: The original database is restored from backup; an exception is thrown. ``` -------------------------------- ### Using the ADO.NET Provider Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/ado-net.md Illustrates how to use the standard ADO.NET classes provided by SqliteWasmBlazor to connect to a database, create tables, and query data. ```APIDOC ## Using the ADO.NET Provider ### Description Utilize standard ADO.NET classes like `SqliteWasmConnection`, `SqliteWasmCommand`, and `SqliteWasmDataReader` to interact with your SQLite database. ### Method N/A (C# Code within Blazor Component) ### Endpoint N/A ### Parameters N/A ### Request Example ```csharp @inject ISqliteWasmDatabaseService DatabaseService @implements IAsyncDisposable

Users

@foreach (var user in users) {
@user.Name (@user.Email)
} @code { private SqliteWasmConnection? connection; private List users = new(); protected override async Task OnInitializedAsync() { // Create connection connection = new SqliteWasmConnection("Data Source=MyApp.db"); await connection.OpenAsync(); // Create table if not exists using var createCmd = connection.CreateCommand(); createCmd.CommandText = @"\n CREATE TABLE IF NOT EXISTS Users (\n Id INTEGER PRIMARY KEY AUTOINCREMENT,\n Name TEXT NOT NULL,\n Email TEXT NOT NULL,\n CreatedAt TEXT NOT NULL )"; await createCmd.ExecuteNonQueryAsync(); // Query data using var queryCmd = connection.CreateCommand(); queryCmd.CommandText = "SELECT Id, Name, Email FROM Users ORDER BY Name"; using var reader = await queryCmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { users.Add(new User { Id = reader.GetInt32(0), Name = reader.GetString(1), Email = reader.GetString(2) }); } } private async Task AddUser(string name, string email) { using var cmd = connection!.CreateCommand(); cmd.CommandText = "INSERT INTO Users (Name, Email, CreatedAt) VALUES ($name, $email, $date)"; // Add parameters cmd.Parameters.Add(new SqliteWasmParameter { ParameterName = "$name", Value = name }); cmd.Parameters.Add(new SqliteWasmParameter { ParameterName = "$email", Value = email }); cmd.Parameters.Add(new SqliteWasmParameter { ParameterName = "$date", Value = DateTime.UtcNow.ToString("O") }); await cmd.ExecuteNonQueryAsync(); } public async ValueTask DisposeAsync() { if (connection is not null) { await connection.CloseAsync(); await connection.DisposeAsync(); } } record User { public int Id { get; init; } public string Name { get; init; } = ""; public string Email { get; init; } = ""; } } ``` ### Response N/A ``` -------------------------------- ### Generate and Apply EF Core Migrations in SqliteWasmBlazor Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/advanced-features.md Demonstrates the command-line steps to generate an EF Core migration and the C# code to apply pending migrations at runtime within a Blazor application. The `InitializeSqliteWasmDatabaseAsync` method is mentioned for automatic application during startup. ```bash # Generate migration (run from models project directory) dotnet ef migrations add InitialCreate --context TodoDbContext ``` ```csharp await dbContext.Database.MigrateAsync(); ``` -------------------------------- ### ADO.NET Provider - Direct SQL Access Source: https://context7.com/b-straub/sqlitewasmblazor/llms.txt Demonstrates how to set up and use the ADO.NET provider for direct SQL access in a Blazor WebAssembly application. This includes initializing the service, creating tables, inserting data with parameters, and querying results using a DataReader. ```APIDOC ## ADO.NET Provider - Direct SQL Access Use the ADO.NET provider for direct SQL access without EF Core. This is useful for lightweight operations, raw SQL queries, or porting existing ADO.NET code. ### Program.cs Setup This C# code demonstrates the minimal setup required in `Program.cs` for ADO.NET-only usage. ```csharp // Program.cs for ADO.NET-only usage (no EF Core) using SqliteWasmBlazor; var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.Services.AddSqliteWasm(); var host = builder.Build(); // Initialize worker bridge without EF Core await host.Services.InitializeSqliteWasmAsync(); await host.RunAsync(); ``` ### Basic SQL Operations (Razor Component) This C# code, intended for a Razor component, shows how to create a connection, define a table, insert data with parameters, and query data using `SqliteWasmConnection` and `SqliteWasmDataReader`. ```csharp @implements IAsyncDisposable @code { private SqliteWasmConnection? connection; protected override async Task OnInitializedAsync() { // Create and open connection connection = new SqliteWasmConnection("Data Source=MyApp.db"); await connection.OpenAsync(); // Create table using var createCmd = connection.CreateCommand(); createCmd.CommandText = @" CREATE TABLE IF NOT EXISTS Users ( Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL, Email TEXT NOT NULL UNIQUE, CreatedAt TEXT NOT NULL )"; await createCmd.ExecuteNonQueryAsync(); // Insert with parameters using var insertCmd = connection.CreateCommand(); insertCmd.CommandText = @" INSERT INTO Users (Name, Email, CreatedAt) VALUES ($name, $email, $date)"; insertCmd.Parameters.Add(new SqliteWasmParameter("$name", "John Doe")); insertCmd.Parameters.Add(new SqliteWasmParameter("$email", "john@example.com")); insertCmd.Parameters.Add(new SqliteWasmParameter("$date", DateTime.UtcNow.ToString("O"))); await insertCmd.ExecuteNonQueryAsync(); // Query with DataReader using var queryCmd = connection.CreateCommand(); queryCmd.CommandText = "SELECT Id, Name, Email FROM Users ORDER BY Name"; using var reader = await queryCmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { var id = reader.GetInt32(0); var name = reader.GetString(1); var email = reader.GetString(2); Console.WriteLine($"User {id}: {name} ({email})"); } } public async ValueTask DisposeAsync() { if (connection is not null) { await connection.CloseAsync(); await connection.DisposeAsync(); } } } ``` ``` -------------------------------- ### Implement Database Import and Export with MessagePack Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/CHANGELOG.md Demonstrates the use of MessagePackFileDownload and MessagePackFileUpload components for efficient binary serialization and schema-validated database operations in Blazor. ```csharp // Export database to MessagePack file // Import database with validation ``` -------------------------------- ### Implement Full-Text Search with FTS5 Source: https://context7.com/b-straub/sqlitewasmblazor/llms.txt Shows how to configure an FTS5 virtual table and perform ranked searches with result highlighting in SQLite WASM. ```csharp public class FTSTodoItem { public int RowId { get; set; } public string? Match { get; set; } public double Rank { get; set; } } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity(entity => { entity.HasNoKey(); entity.ToTable("FTSTodoItem"); entity.Property(e => e.Match).HasColumnName("FTSTodoItem"); }); } migrationBuilder.Sql(@" CREATE VIRTUAL TABLE FTSTodoItem USING fts5( Title, Description, content='TodoItems', content_rowid='Id' ); "); ``` ```csharp @inject IDbContextFactory DbFactory @code { private async Task> SearchTodosAsync(string searchQuery) { await using var db = await DbFactory.CreateDbContextAsync(); var sanitizedQuery = searchQuery.Replace("\"", "\"\""); var results = await db.Database .SqlQuery($@" SELECT t.Id, t.Title, t.Description, highlight(FTSTodoItem, 0, '', '') AS HighlightedTitle, highlight(FTSTodoItem, 1, '', '') AS HighlightedDescription, rank AS Rank FROM FTSTodoItem INNER JOIN TodoItems t ON FTSTodoItem.rowid = t.Id WHERE FTSTodoItem MATCH {sanitizedQuery} ORDER BY rank LIMIT 50") .AsNoTracking() .ToListAsync(); return results; } } ``` -------------------------------- ### ADO.NET Provider Usage with SqliteWasmBlazor Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/ado-net.md Demonstrates the standard ADO.NET operations using SqliteWasmBlazor, including creating connections, executing SQL commands for table creation and data querying, and reading results with a data reader. It also shows how to add parameters to commands to prevent SQL injection. ```csharp @inject ISqliteWasmDatabaseService DatabaseService @implements IAsyncDisposable

Users

@foreach (var user in users) {
@user.Name (@user.Email)
} @code { private SqliteWasmConnection? connection; private List users = new(); protected override async Task OnInitializedAsync() { // Create connection connection = new SqliteWasmConnection("Data Source=MyApp.db"); await connection.OpenAsync(); // Create table if not exists using var createCmd = connection.CreateCommand(); createCmd.CommandText = @" CREATE TABLE IF NOT EXISTS Users ( Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL, Email TEXT NOT NULL, CreatedAt TEXT NOT NULL )"; await createCmd.ExecuteNonQueryAsync(); // Query data using var queryCmd = connection.CreateCommand(); queryCmd.CommandText = "SELECT Id, Name, Email FROM Users ORDER BY Name"; using var reader = await queryCmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { users.Add(new User { Id = reader.GetInt32(0), Name = reader.GetString(1), Email = reader.GetString(2) }); } } private async Task AddUser(string name, string email) { using var cmd = connection!.CreateCommand(); cmd.CommandText = "INSERT INTO Users (Name, Email, CreatedAt) VALUES ($name, $email, $date)"; // Add parameters cmd.Parameters.Add(new SqliteWasmParameter { ParameterName = "$name", Value = name }); cmd.Parameters.Add(new SqliteWasmParameter { ParameterName = "$email", Value = email }); cmd.Parameters.Add(new SqliteWasmParameter { ParameterName = "$date", Value = DateTime.UtcNow.ToString("O") }); await cmd.ExecuteNonQueryAsync(); } public async ValueTask DisposeAsync() { if (connection is not null) { await connection.CloseAsync(); await connection.DisposeAsync(); } } record User { public int Id { get; init; } public string Name { get; init; } = ""; public string Email { get; init; } = ""; } } ``` -------------------------------- ### Implement Incremental Database Export and Import Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/CHANGELOG.md Demonstrates how to use MessagePack components for delta-based synchronization. It handles exporting only modified items since the last checkpoint and importing data with specific conflict resolution strategies. ```csharp // Export only changes since last checkpoint (delta export) // Import with conflict resolution strategy ``` -------------------------------- ### Implement Multi-View Data Synchronization with IDbContextFactory Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/patterns.md Demonstrates how to use IDbContextFactory for short-lived database contexts and a singleton notification service to synchronize state across multiple UI views without shared state conflicts. ```csharp private async Task AddTodoAsync() { await using var context = await DbContextFactory.CreateDbContextAsync(); context.TodoItems.Add(newTodo); await context.SaveChangesAsync(); Notifier.NotifyDataChanged(); } public sealed class TodoDataNotifier { public event Action? OnDataChanged; public void NotifyDataChanged() => OnDataChanged?.Invoke(); } protected override void OnInitialized() { Notifier.OnDataChanged += OnDataChanged; } private void OnDataChanged() { _ = InvokeAsync(async () => { await LoadDataAsync(); StateHasChanged(); }); } ``` -------------------------------- ### Generate Migrations via CLI Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/multi-database.md Use the dotnet ef command-line tool to generate migrations for each specific DbContext into separate directories. ```bash dotnet ef migrations add InitialCreate --context TodoDbContext --output-dir Migrations dotnet ef migrations add InitialCreate --context NoteDbContext --output-dir NoteMigrations ``` -------------------------------- ### Search with Highlighting using FTS5 Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/advanced-features.md C# code demonstrating how to perform a full-text search using FTS5 and retrieve results with highlighted matches. It utilizes `SqlQuery` to execute a SQL query that includes the `highlight()` function and joins with the original data table. ```csharp var results = dbContext.Database .SqlQuery($" SELECT t.Id, t.Title, t.Description, highlight(FTSTodoItem, 0, '', '') AS HighlightedTitle, highlight(FTSTodoItem, 1, '', '') AS HighlightedDescription, rank AS Rank FROM FTSTodoItem INNER JOIN TodoItems t ON FTSTodoItem.rowid = t.Id WHERE FTSTodoItem MATCH {searchQuery} ORDER BY rank") .AsNoTracking(); ``` -------------------------------- ### Manage SQLite Databases with ISqliteWasmDatabaseService Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/ado-net.md Demonstrates how to use the ISqliteWasmDatabaseService to perform common database management tasks such as checking existence, closing connections, deleting, and renaming databases. These operations are asynchronous and require the service to be injected. ```csharp @inject ISqliteWasmDatabaseService DatabaseService @code { private async Task ResetDatabaseAsync() { // Check if database exists if (await DatabaseService.ExistsDatabaseAsync("MyApp.db")) { // Close any open connections first await DatabaseService.CloseDatabaseAsync("MyApp.db"); // Delete the database await DatabaseService.DeleteDatabaseAsync("MyApp.db"); } // Recreate... } private async Task BackupDatabaseAsync() { // Rename for backup await DatabaseService.RenameDatabaseAsync("MyApp.db", "MyApp.backup.db"); } } ``` -------------------------------- ### Using Transactions Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/ado-net.md Demonstrates how to manage database transactions using `SqliteWasmTransaction` for atomic operations. ```APIDOC ## Using Transactions ### Description Implement database transactions to ensure atomicity for multiple SQL operations, including commit and rollback. ### Method N/A (C# Code) ### Endpoint N/A ### Parameters N/A ### Request Example ```csharp await using var connection = new SqliteWasmConnection("Data Source=MyApp.db"); await connection.OpenAsync(); // Start transaction await using var transaction = await connection.BeginTransactionAsync(); try { // Execute multiple commands await using var cmd1 = connection.CreateCommand(); cmd1.Transaction = transaction; cmd1.CommandText = "INSERT INTO Users (Name, Email) VALUES ('Alice', 'alice@example.com')"; await cmd1.ExecuteNonQueryAsync(); await using var cmd2 = connection.CreateCommand(); cmd2.Transaction = transaction; cmd2.CommandText = "UPDATE Users SET Email = 'newemail@example.com' WHERE Name = 'Bob'"; await cmd2.ExecuteNonQueryAsync(); // Commit transaction await transaction.CommitAsync(); } catch { // Rollback on error await transaction.RollbackAsync(); throw; } ``` ### Response N/A ``` -------------------------------- ### ADO.NET Database Operations with SqliteWasmBlazor Source: https://context7.com/b-straub/sqlitewasmblazor/llms.txt Demonstrates basic database operations using the ADO.NET provider in a Blazor component. It covers creating a table, inserting data with parameters, querying data using a DataReader, and managing the connection lifecycle. ```csharp @implements IAsyncDisposable @code { private SqliteWasmConnection? connection; protected override async Task OnInitializedAsync() { // Create and open connection connection = new SqliteWasmConnection("Data Source=MyApp.db"); await connection.OpenAsync(); // Create table using var createCmd = connection.CreateCommand(); createCmd.CommandText = @" CREATE TABLE IF NOT EXISTS Users ( Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL, Email TEXT NOT NULL UNIQUE, CreatedAt TEXT NOT NULL )"; await createCmd.ExecuteNonQueryAsync(); // Insert with parameters using var insertCmd = connection.CreateCommand(); insertCmd.CommandText = @" INSERT INTO Users (Name, Email, CreatedAt) VALUES ($name, $email, $date)"; insertCmd.Parameters.Add(new SqliteWasmParameter("$name", "John Doe")); insertCmd.Parameters.Add(new SqliteWasmParameter("$email", "john@example.com")); insertCmd.Parameters.Add(new SqliteWasmParameter("$date", DateTime.UtcNow.ToString("O"))); await insertCmd.ExecuteNonQueryAsync(); // Query with DataReader using var queryCmd = connection.CreateCommand(); queryCmd.CommandText = "SELECT Id, Name, Email FROM Users ORDER BY Name"; using var reader = await queryCmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { var id = reader.GetInt32(0); var name = reader.GetString(1); var email = reader.GetString(2); Console.WriteLine($"User {id}: {name} ({email})"); } } public async ValueTask DisposeAsync() { if (connection is not null) { await connection.CloseAsync(); await connection.DisposeAsync(); } } } ``` -------------------------------- ### Export and Import Raw SQLite Database Files Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/advanced-features.md Demonstrates how to export and import entire SQLite database files (.db) directly to and from OPFS using the `ISqliteWasmDatabaseService`. The export operation retrieves the database as a byte array, and the import operation loads a byte array into a specified database file. Both operations close the database in the worker, and EF Core automatically re-opens it for subsequent queries. ```csharp @inject ISqliteWasmDatabaseService DatabaseService // Export raw .db file byte[] data = await DatabaseService.ExportDatabaseAsync("TodoDb.db"); // Import raw .db file (validates SQLite header) await DatabaseService.ImportDatabaseAsync("TodoDb.db", data); ``` -------------------------------- ### Registering SqliteWasm Service in Blazor Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/README.md Demonstrates how to register the SqliteWasm service in the Blazor application's Program.cs file using dependency injection. This makes the database services available throughout the application. ```csharp builder.Services.AddSqliteWasm(); ``` -------------------------------- ### Configure SqliteWasm in Program.cs Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/README.md Configures the DbContextFactory and registers the SqliteWasm services in the Blazor WebAssembly host builder. ```csharp using SqliteWasmBlazor; var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.Services.AddDbContextFactory(options => { var connection = new SqliteWasmConnection("Data Source=TodoDb.db"); options.UseSqliteWasm(connection); }); builder.Services.AddSingleton(); builder.Services.AddSqliteWasm(); var host = builder.Build(); await host.Services.InitializeSqliteWasmDatabaseAsync(); await host.RunAsync(); ``` -------------------------------- ### Create Design-Time DbContext Factory Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/multi-database.md Implement IDesignTimeDbContextFactory to enable Entity Framework Core tools to generate migrations for specific database contexts. ```csharp public class NoteDbContextFactory : IDesignTimeDbContextFactory { public NoteDbContext CreateDbContext(string[] args) { var optionsBuilder = new DbContextOptionsBuilder(); optionsBuilder.UseSqlite("Data Source=:memory:"); return new NoteDbContext(optionsBuilder.Options); } } ``` -------------------------------- ### Register Multiple DbContexts in Program.cs Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/multi-database.md Configure the dependency injection container to register multiple database factories, each pointing to a unique SQLite database file. ```csharp builder.Services.AddDbContextFactory(options => { var connection = new SqliteWasmConnection("Data Source=TodoDb.db"); options.UseSqliteWasm(connection); }); builder.Services.AddDbContextFactory(options => { var connection = new SqliteWasmConnection("Data Source=NotesDb.db"); options.UseSqliteWasm(connection); }); builder.Services.AddSingleton(); builder.Services.AddSqliteWasm(); ``` -------------------------------- ### Handle Database Initialization Errors in Blazor Source: https://context7.com/b-straub/sqlitewasmblazor/llms.txt Displays user-friendly error messages for database initialization failures, such as multi-tab conflicts or schema mismatches. Provides options to reset the database if errors are incompatible. ```csharp @inject IDBInitializationService InitService @inject ISqliteWasmDatabaseService DatabaseService @inject IDbContextFactory DbFactory @if (!string.IsNullOrEmpty(InitService.ErrorMessage)) {

@InitService.ErrorMessage

@if (InitService.ErrorMessage.Contains("locked")) {

Please close other tabs and refresh the page.

} else if (InitService.ErrorMessage.Contains("incompatible")) { }
} @code { private async Task ResetDatabaseAsync() { await DatabaseService.DeleteDatabaseAsync("TodoDb.db"); // Clear error and reinitialize InitService.ErrorMessage = null; await using var context = await DbFactory.CreateDbContextAsync(); await context.Database.MigrateAsync(); // Refresh the page to complete reinitialization Navigation.NavigateTo(Navigation.Uri, forceLoad: true); } } ``` -------------------------------- ### Database Migration Management Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/docs/advanced-features.md Explains how to generate and apply EF Core migrations within a Blazor WebAssembly environment. ```APIDOC ## Migrations Management ### Description Provides instructions for generating and applying EF Core migrations to ensure database schema consistency in a WebAssembly environment. ### Method CLI / Runtime ### Parameters - **context** (string) - Required - The DbContext class name to target for migrations. ### Usage Example ```bash # Generate migration dotnet ef migrations add InitialCreate --context TodoDbContext # Apply migrations at runtime await dbContext.Database.MigrateAsync(); ``` ``` -------------------------------- ### Implement Delta Export and Import with Checkpoints in C# Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/CHANGELOG.md Provides methods to query database changes since the last checkpoint, merge incoming delta updates with conflict resolution logic, and create new synchronization checkpoints. These methods utilize Entity Framework Core to manage state and ensure data integrity. ```csharp private async Task<(List Items, int TotalCount)> GetDeltaTodoItemsPageAsync(int skip, int take) { await using var context = await DbContextFactory.CreateDbContextAsync(); var lastCheckpoint = await context.SyncState.OrderByDescending(s => s.CreatedAt).FirstOrDefaultAsync(); var lastCheckpointTime = lastCheckpoint?.CreatedAt ?? DateTime.MinValue; var query = context.TodoItems.Where(t => (t.UpdatedAt > lastCheckpointTime && !t.IsDeleted) || (t.IsDeleted && t.DeletedAt.HasValue && t.DeletedAt.Value > lastCheckpointTime)).OrderBy(t => t.UpdatedAt); var totalCount = await query.CountAsync(); var items = await query.Skip(skip).Take(take).Select(t => t.ToDto()).ToListAsync(); return (items, totalCount); } private async Task DeltaMergeTodoItemsAsync(List dtos) { await using var context = await DbContextFactory.CreateDbContextAsync(); foreach (var dto in dtos) { var existingItem = await context.TodoItems.FirstOrDefaultAsync(t => t.Id == dto.Id); if (existingItem is not null) { var shouldUpdate = _conflictResolution switch { ConflictResolutionStrategy.LastWriteWins => dto.UpdatedAt > existingItem.UpdatedAt, ConflictResolutionStrategy.LocalWins => false, ConflictResolutionStrategy.DeltaWins => true, _ => throw new InvalidOperationException($"Unknown strategy: {_conflictResolution}") }; if (shouldUpdate) { existingItem.Title = dto.Title; existingItem.UpdatedAt = dto.UpdatedAt; existingItem.IsDeleted = dto.IsDeleted; existingItem.DeletedAt = dto.DeletedAt; } } else { context.TodoItems.Add(dto.ToEntity()); } } await context.SaveChangesAsync(); await context.CreateCheckpointAsync($"Auto checkpoint after delta import ({dtos.Count} items)", "Auto"); } public static async Task CreateCheckpointAsync(this TodoDbContext context, string description, string checkpointType = "Auto", CancellationToken cancellationToken = default) { var activeCount = await context.TodoItems.CountAsync(t => !t.IsDeleted, cancellationToken); var tombstoneCount = await context.TodoItems.CountAsync(t => t.IsDeleted, cancellationToken); var checkpoint = new SyncState { CreatedAt = DateTime.UtcNow, Description = description, ActiveItemCount = activeCount, TombstoneCount = tombstoneCount, CheckpointType = checkpointType }; context.SyncState.Add(checkpoint); await context.SaveChangesAsync(cancellationToken); return checkpoint; } ``` -------------------------------- ### Perform Raw Database Import and Export Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/CHANGELOG.md Handles raw .db file transfers to and from OPFS, automatically managing worker connection states. ```csharp @inject ISqliteWasmDatabaseService DatabaseService // Export: closes DB for consistent snapshot, returns raw bytes byte[] data = await DatabaseService.ExportDatabaseAsync("TodoDb.db"); // Import: writes raw .db file to OPFS (validates SQLite header) await DatabaseService.ImportDatabaseAsync("TodoDb.db", data); ``` -------------------------------- ### Migrate SqliteWasmConnection Log Level Configuration Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/CHANGELOG.md Shows the transition from custom SqliteWasmLogLevel to standard Microsoft.Extensions.Logging.LogLevel for the SqliteWasmConnection constructor. ```csharp // Old (0.6.6-pre and earlier) var connection = new SqliteWasmConnection("Data Source=MyDb.db", SqliteWasmLogLevel.Warning); // New (0.6.7-pre and later) using Microsoft.Extensions.Logging; // Add this using // Default is LogLevel.Warning, so you can omit it: var connection = new SqliteWasmConnection("Data Source=MyDb.db"); // Or specify a different level: var connection = new SqliteWasmConnection("Data Source=MyDb.db", LogLevel.Error); ``` -------------------------------- ### Use ISqliteWasmDatabaseService in Blazor Components Source: https://github.com/b-straub/sqlitewasmblazor/blob/master/README.md Demonstrates how to inject and use the database service within a Blazor component to perform database resets, exports, and imports. ```csharp @inject ISqliteWasmDatabaseService DatabaseService @code { private async Task ResetDatabaseAsync() { await DatabaseService.DeleteDatabaseAsync("MyApp.db"); await using var context = await DbContextFactory.CreateDbContextAsync(); await context.Database.MigrateAsync(); } private async Task ExportAsync() { byte[] data = await DatabaseService.ExportDatabaseAsync("MyApp.db"); } private async Task ImportAsync(byte[] data) { await DatabaseService.ImportDatabaseAsync("MyApp.db", data); } } ``` -------------------------------- ### Using DbContextFactory in Blazor Components Source: https://context7.com/b-straub/sqlitewasmblazor/llms.txt Demonstrates how to use IDbContextFactory to create and manage short-lived DbContext instances within Blazor components for efficient database operations and to avoid tracking conflicts. ```APIDOC ## Using DbContextFactory in Components Use IDbContextFactory to create short-lived DbContext instances for each database operation. This is the recommended pattern for Blazor applications to avoid tracking conflicts. ```csharp @page "/todos" @inject IDbContextFactory DbFactory

Todo List

@foreach (var todo in todos) {
@todo.Title
} @code { private List todos = new(); private string newTitle = string.Empty; protected override async Task OnInitializedAsync() { await LoadTodosAsync(); } private async Task LoadTodosAsync() { await using var db = await DbFactory.CreateDbContextAsync(); todos = await db.TodoItems .Include(t => t.Category) .OrderByDescending(t => t.CreatedAt) .ToListAsync(); } private async Task AddTodo() { if (string.IsNullOrWhiteSpace(newTitle)) return; await using var db = await DbFactory.CreateDbContextAsync(); db.TodoItems.Add(new TodoItem { Title = newTitle, CreatedAt = DateTime.UtcNow }); await db.SaveChangesAsync(); newTitle = string.Empty; await LoadTodosAsync(); } private async Task SaveTodo(TodoItem todo) { await using var db = await DbFactory.CreateDbContextAsync(); db.TodoItems.Update(todo); if (todo.IsCompleted && !todo.CompletedAt.HasValue) { todo.CompletedAt = DateTime.UtcNow; } await db.SaveChangesAsync(); } private async Task DeleteTodo(TodoItem todo) { await using var db = await DbFactory.CreateDbContextAsync(); db.TodoItems.Remove(todo); await db.SaveChangesAsync(); await LoadTodosAsync(); } } ``` ```