### Install Respawn via NuGet Source: https://context7.com/jbogard/respawn/llms.txt Use the Package Manager Console or .NET CLI to install the Respawn NuGet package. ```bash # Package Manager Console Install-Package Respawn ``` ```bash # .NET CLI dotnet add package Respawn ``` -------------------------------- ### Complete Integration Test Fixture with Respawn Source: https://context7.com/jbogard/respawn/llms.txt An example of setting up an xUnit integration test fixture using Respawn for database resets. It demonstrates initializing the connection, creating the respawner with specific options, and resetting the database before tests. ```csharp using Respawn; using Microsoft.Data.SqlClient; using Xunit; public class IntegrationTestFixture : IAsyncLifetime { private const string ConnectionString = "Server=localhost;Database=IntegrationTests;Trusted_Connection=True;TrustServerCertificate=True;"; public SqlConnection Connection { get; private set; } = null!; private Respawner _respawner = null!; public async Task InitializeAsync() { Connection = new SqlConnection(ConnectionString); await Connection.OpenAsync(); _respawner = await Respawner.CreateAsync(Connection, new RespawnerOptions { TablesToIgnore = new[] { "__EFMigrationsHistory" }, SchemasToExclude = new[] { "sys", "INFORMATION_SCHEMA" }, WithReseed = true, CheckTemporalTables = true }); } public async Task ResetDatabaseAsync() { await _respawner.ResetAsync(Connection); } public async Task DisposeAsync() { await Connection.DisposeAsync(); } } [Collection("Database")] public class OrderTests : IAsyncLifetime { private readonly IntegrationTestFixture _fixture; public OrderTests(IntegrationTestFixture fixture) { _fixture = fixture; } public async Task InitializeAsync() { await _fixture.ResetDatabaseAsync(); } public Task DisposeAsync() => Task.CompletedTask; [Fact] public async Task CreateOrder_WithValidCustomer_Succeeds() { // Arrange - database is clean await using var cmd = _fixture.Connection.CreateCommand(); cmd.CommandText = "INSERT INTO Customers (Id, Name) VALUES (1, 'John Doe')"; await cmd.ExecuteNonQueryAsync(); // Act cmd.CommandText = "INSERT INTO Orders (CustomerId, Total) VALUES (1, 99.99)"; await cmd.ExecuteNonQueryAsync(); // Assert cmd.CommandText = "SELECT COUNT(*) FROM Orders WHERE CustomerId = 1"; var count = (int)await cmd.ExecuteScalarAsync()!; Assert.Equal(1, count); } [Fact] public async Task GetOrders_EmptyDatabase_ReturnsZero() { // Database was reset before this test - starts empty await using var cmd = _fixture.Connection.CreateCommand(); cmd.CommandText = "SELECT COUNT(*) FROM Orders"; var count = (int)await cmd.ExecuteScalarAsync()!; Assert.Equal(0, count); } } ``` -------------------------------- ### Reseed Identity Columns After Reset Source: https://context7.com/jbogard/respawn/llms.txt Set `WithReseed = true` in `RespawnerOptions` to reset identity or auto-increment columns to their initial seed values after data deletion. This ensures new entries start with the expected IDs. ```csharp using Respawn; var respawner = await Respawner.CreateAsync(connection, new RespawnerOptions { WithReseed = true }); // Before reset: table has 100 rows, next ID would be 101 // INSERT INTO Products (Name) VALUES ('Test') -- ID = 101 await respawner.ResetAsync(connection); // After reset: identity is reseeded // INSERT INTO Products (Name) VALUES ('Test') -- ID = 1 // Also works with custom seed values // CREATE TABLE Products (Id INT IDENTITY(1000, 1), Name VARCHAR(100)) // After reset, next ID will be 1000 again ``` -------------------------------- ### Create a Respawner Instance Source: https://context7.com/jbogard/respawn/llms.txt Use the Respawner.CreateAsync factory method to analyze the database schema and create a respawner. The database adapter is automatically inferred from the connection type. The generated delete SQL is cached for reuse. ```csharp using Respawn; using Microsoft.Data.SqlClient; // Basic usage - adapter is inferred from connection type await using var connection = new SqlConnection("Server=localhost;Database=TestDb;Trusted_Connection=True;"); await connection.OpenAsync(); var respawner = await Respawner.CreateAsync(connection); // The respawner caches the delete SQL for reuse Console.WriteLine(respawner.DeleteSql); // Output: DELETE FROM [dbo].[Orders]; DELETE FROM [dbo].[Customers]; ... ``` -------------------------------- ### RespawnerOptions Configuration Reference Source: https://context7.com/jbogard/respawn/llms.txt A comprehensive reference for `RespawnerOptions`, detailing how to configure table and schema inclusion/exclusion, temporal table handling, identity re-seeding, command timeouts, custom delete statements, and database adapters. ```csharp using Respawn; using Respawn.Graph; var options = new RespawnerOptions { // Tables to skip during reset (preserve data) TablesToIgnore = new Table[] { "LookupTable", new Table("schema", "TableName") }, // Tables to include (only these will be reset) TablesToInclude = new Table[] { "Orders", "Customers" }, // Schemas to include in reset SchemasToInclude = new[] { "public", "dbo" }, // Schemas to exclude from reset SchemasToExclude = new[] { "audit", "archive" }, // Handle SQL Server temporal tables CheckTemporalTables = true, // Reset identity columns to initial seed WithReseed = true, // Command timeout in seconds CommandTimeout = 120, // Custom delete statement formatter FormatDeleteStatement = table => $"DELETE FROM {table.GetFullName('"')};", ``` ```csharp // Explicit database adapter (auto-detected if null) DbAdapter = DbAdapter.SqlServer }; var respawner = await Respawner.CreateAsync(connection, options); ``` -------------------------------- ### Create Respawner with Included Schemas and DB Adapter Source: https://github.com/jbogard/respawn/blob/main/README.md Configure a Respawner to only include specific schemas and optionally specify the database adapter. The adapter is often inferred from the connection string. ```csharp var respawner = await Respawner.CreateAsync(connection, new RespawnerOptions { SchemasToInclude = new [] { "public" }, DbAdapter = DbAdapter.Postgres // ← optional, inferred from the connection for SQL Server, PostgreSQL, MySQL, Oracle and Informix }); ``` -------------------------------- ### Create Respawner with Ignored Tables Source: https://github.com/jbogard/respawn/blob/main/README.md Initialize a Respawner instance, specifying tables and schemas to exclude from the reset process. This is useful for maintaining specific data or system tables. ```csharp var respawner = await Respawner.CreateAsync(connection, new RespawnerOptions { TablesToIgnore = new Table[] { "sysdiagrams", "tblUser", "tblObjectType", new Table("MyOtherSchema", "MyOtherTable") }, SchemasToExclude = new [] { "RoundhousE" } }); ``` -------------------------------- ### Reset Database Before Each Test Source: https://context7.com/jbogard/respawn/llms.txt Implement IAsyncLifetime to initialize and dispose of the database connection. Create the respawner once and call ResetAsync before each test to ensure a clean database state. ```csharp using Respawn; using Microsoft.Data.SqlClient; using Xunit; public class DatabaseTests : IAsyncLifetime { private static Respawner _respawner = null!; private SqlConnection _connection = null!; public async Task InitializeAsync() { _connection = new SqlConnection("Server=localhost;Database=TestDb;Trusted_Connection=True;"); await _connection.OpenAsync(); // Create respawner once (expensive operation) _respawner ??= await Respawner.CreateAsync(_connection); // Reset database before each test await _respawner.ResetAsync(_connection); } public async Task DisposeAsync() { await _connection.DisposeAsync(); } [Fact] public async Task Should_Insert_Customer() { // Database starts clean - no existing data await using var cmd = _connection.CreateCommand(); cmd.CommandText = "INSERT INTO Customers (Name) VALUES ('Test')"; await cmd.ExecuteNonQueryAsync(); cmd.CommandText = "SELECT COUNT(*) FROM Customers"; var count = (int)await cmd.ExecuteScalarAsync()!; Assert.Equal(1, count); } } ``` -------------------------------- ### Reset Database using Connection String Name Source: https://github.com/jbogard/respawn/blob/main/README.md Perform a database reset using the Respawner instance, referencing the connection string by its name. This is a common approach in test fixtures. ```csharp await respawner.ResetAsync("MyConnectionStringName"); ``` -------------------------------- ### Configure Tables to Include for Reset Source: https://context7.com/jbogard/respawn/llms.txt Use the `TablesToInclude` option in `RespawnerOptions` to reset only a specified subset of tables. All other tables will retain their data. ```csharp using Respawn; using Respawn.Graph; var respawner = await Respawner.CreateAsync(connection, new RespawnerOptions { TablesToInclude = new Table[] { "Orders", "OrderItems", new Table("sales", "Transactions") } }); // Only Orders, OrderItems, and sales.Transactions will be deleted await respawner.ResetAsync(connection); // Customers, Products, etc. will retain their data ``` -------------------------------- ### Configure Respawn for MySQL Source: https://context7.com/jbogard/respawn/llms.txt Respawn automatically detects MySQL connections. Use schema filtering, specifying the database name as the schema, as MySQL treats schemas as databases. ```csharp using Respawn; using MySql.Data.MySqlClient; await using var connection = new MySqlConnection( "Server=localhost;Database=testdb;User=root;Password=secret"); await connection.OpenAsync(); var respawner = await Respawner.CreateAsync(connection, new RespawnerOptions { SchemasToInclude = new[] { "testdb" } // MySQL schema = database name }); await respawner.ResetAsync(connection); ``` -------------------------------- ### Configure Respawn for PostgreSQL Source: https://context7.com/jbogard/respawn/llms.txt Respawn automatically detects PostgreSQL connections. Use schema filtering to target specific schemas within your PostgreSQL database. ```csharp using Respawn; using Npgsql; await using var connection = new NpgsqlConnection( "Host=localhost;Database=testdb;Username=postgres;Password=secret"); await connection.OpenAsync(); var respawner = await Respawner.CreateAsync(connection, new RespawnerOptions { SchemasToInclude = new[] { "public" } }); // Insert test data await using var cmd = connection.CreateCommand(); cmd.CommandText = "INSERT INTO customers (name) VALUES ('Test Customer')"; await cmd.ExecuteNonQueryAsync(); // Reset to clean state await respawner.ResetAsync(connection); // Table is now empty cmd.CommandText = "SELECT COUNT(*) FROM customers"; var count = (long)await cmd.ExecuteScalarAsync()!; // count == 0 ``` -------------------------------- ### Filter Database Schemas for Reset Source: https://context7.com/jbogard/respawn/llms.txt Use `SchemasToInclude` or `SchemasToExclude` to specify which database schemas Respawn should affect during a reset. This is useful for targeting specific parts of your database. ```csharp using Respawn; // Only reset tables in specific schemas var respawner = await Respawner.CreateAsync(connection, new RespawnerOptions { SchemasToInclude = new[] { "public", "sales" } }); // Or exclude specific schemas var respawnerWithExcludes = await Respawner.CreateAsync(connection, new RespawnerOptions { SchemasToExclude = new[] { "audit", "archive", "system" } }); // Reset only affects tables in included/non-excluded schemas await respawner.ResetAsync(connection); ``` -------------------------------- ### Explicitly Specify Database Adapter Source: https://context7.com/jbogard/respawn/llms.txt When automatic detection fails, explicitly set the `DbAdapter` property in `RespawnerOptions` to the correct database type for your connection. ```csharp using Respawn; // SQL Server var sqlServerRespawner = await Respawner.CreateAsync(connection, new RespawnerOptions { DbAdapter = DbAdapter.SqlServer }); // PostgreSQL var postgresRespawner = await Respawner.CreateAsync(connection, new RespawnerOptions { DbAdapter = DbAdapter.Postgres }); // MySQL var mysqlRespawner = await Respawner.CreateAsync(connection, new RespawnerOptions { DbAdapter = DbAdapter.MySql }); // Oracle var oracleRespawner = await Respawner.CreateAsync(connection, new RespawnerOptions { DbAdapter = DbAdapter.Oracle }); // SQLite var sqliteRespawner = await Respawner.CreateAsync(connection, new RespawnerOptions { DbAdapter = DbAdapter.Sqlite }); // Informix var informixRespawner = await Respawner.CreateAsync(connection, new RespawnerOptions { DbAdapter = DbAdapter.Informix }); // DB2 var db2Respawner = await Respawner.CreateAsync(connection, new RespawnerOptions { DbAdapter = DbAdapter.DB2 }); // Snowflake var snowflakeRespawner = await Respawner.CreateAsync(connection, new RespawnerOptions { DbAdapter = DbAdapter.Snowflake }); ``` -------------------------------- ### Configure Tables to Ignore During Reset Source: https://context7.com/jbogard/respawn/llms.txt Use the `TablesToIgnore` option in `RespawnerOptions` to preserve data in specific tables, such as system tables or reference data, during the reset process. Tables can be specified by name or with schema qualification. ```csharp using Respawn; using Respawn.Graph; var respawner = await Respawner.CreateAsync(connection, new RespawnerOptions { TablesToIgnore = new Table[] { "sysdiagrams", // System tables "tblUser", // Reference data "tblObjectType", // Lookup table new Table("dbo", "Countries"), // Schema-qualified table new Table("config", "Settings") // Different schema } }); // Reset will skip the ignored tables await respawner.ResetAsync(connection); // Verify: ignored tables retain their data // SELECT COUNT(*) FROM tblUser -- Still has data // SELECT COUNT(*) FROM Orders -- Now empty ``` -------------------------------- ### Handle SQL Server Temporal Tables During Reset Source: https://context7.com/jbogard/respawn/llms.txt Enable `CheckTemporalTables = true` to manage SQL Server temporal tables. Respawn will temporarily disable system versioning, reset data in both main and history tables, and then re-enable versioning. ```csharp using Respawn; var respawner = await Respawner.CreateAsync(connection, new RespawnerOptions { CheckTemporalTables = true }); // Respawn will: // 1. Disable system versioning on temporal tables // 2. Delete data from both main and history tables // 3. Re-enable system versioning await respawner.ResetAsync(connection); // Both the temporal table and its history table are now empty ``` -------------------------------- ### Reset Database using Open DbConnection Source: https://github.com/jbogard/respawn/blob/main/README.md Reset the database using an already open DbConnection object. This method is particularly useful when working with non-SQL Server databases or when managing connections manually. ```csharp using (var conn = new NpgsqlConnection("ConnectionString")) { await conn.OpenAsync(); await respawner.ResetAsync(conn); } ``` -------------------------------- ### Set Command Timeout for Delete Operations Source: https://context7.com/jbogard/respawn/llms.txt Configure the `CommandTimeout` option to specify the maximum duration in seconds for delete operations. This is useful for large databases where operations might take longer. ```csharp using Respawn; var respawner = await Respawner.CreateAsync(connection, new RespawnerOptions { CommandTimeout = 300 // 5 minutes timeout for large databases }); await respawner.ResetAsync(connection); ``` -------------------------------- ### Customize Delete Statements with FormatDeleteStatement Source: https://context7.com/jbogard/respawn/llms.txt Use `FormatDeleteStatement` to define custom SQL for deleting data from specific tables. This allows for soft deletes or conditional deletions based on table name. ```csharp using Respawn; var respawner = await Respawner.CreateAsync(connection, new RespawnerOptions { FormatDeleteStatement = table => { // Soft delete for audit tables if (table.Name.StartsWith("Audit")) { return $"UPDATE {table.GetFullName('"')} SET IsDeleted = 1;"; } // Conditional delete for specific tables if (table.Name == "Logs") { return $"DELETE FROM {table.GetFullName('"')} WHERE CreatedDate < DATEADD(day, -30, GETDATE());"; } // Default delete behavior return $"DELETE FROM {table.GetFullName('"')};"; } }); await respawner.ResetAsync(connection); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.