diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9c00ca1..7144b76 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,9 +11,9 @@ jobs:
build:
strategy:
matrix:
- os: [windows-latest]
+ os: [ubuntu-latest]
fail-fast: false
- runs-on: windows-latest
+ runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -23,8 +23,6 @@ jobs:
uses: actions/setup-dotnet@v1
with:
dotnet-version: '8.0.x'
- - name: Start SQL Local DB
- run: sqllocaldb start mssqllocaldb
- name: Build and Test
run: ./Build.ps1
shell: pwsh
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 8e85079..d7aff19 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -20,8 +20,6 @@ jobs:
uses: actions/setup-dotnet@v1
with:
dotnet-version: '8.0.x'
- - name: Start SQL Local DB
- run: sqllocaldb start mssqllocaldb
- name: Build and Test
run: ./Build.ps1
shell: pwsh
diff --git a/Build.ps1 b/Build.ps1
index 53056ab..d536afe 100644
--- a/Build.ps1
+++ b/Build.ps1
@@ -30,10 +30,6 @@ exec { & dotnet clean --configuration Release }
exec { & dotnet build --configuration Release }
-if (-Not (Test-Path 'env:CI')) {
- exec { & docker-compose up -d }
-}
-
exec { & dotnet test --configuration Release --results-directory $artifacts --no-build --logger trx --verbosity=normal }
exec { & dotnet pack .\Respawn\Respawn.csproj --configuration Release --output $artifacts --no-build }
diff --git a/Directory.Build.props b/Directory.Build.props
index 2825fa0..2f9a220 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,7 +1,10 @@
- 10.0
+ 12.0
$(NoWarn);CS1701;CS1702;CS1591
true
+
+ $([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::get_OSX())))
+ $([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::get_Windows())))
diff --git a/Push.ps1 b/Push.ps1
index 9663563..989042d 100644
--- a/Push.ps1
+++ b/Push.ps1
@@ -6,7 +6,7 @@ if ([string]::IsNullOrEmpty($Env:NUGET_API_KEY)) {
} else {
Get-ChildItem $artifacts -Filter "*.nupkg" | ForEach-Object {
Write-Host "$($scriptName): Pushing $($_.Name)"
- dotnet nuget push $_ --source $Env:NUGET_URL --api-key $Env:NUGET_API_KEY
+ dotnet nuget push $_ --source $Env:NUGET_URL --api-key $Env:NUGET_API_KEY --skip-duplicate
if ($lastexitcode -ne 0) {
throw ("Exec: " + $errorMessage)
}
diff --git a/Respawn.DatabaseTests/DB2Tests.cs b/Respawn.DatabaseTests/DB2Tests.cs
index c1896ac..df5da1e 100644
--- a/Respawn.DatabaseTests/DB2Tests.cs
+++ b/Respawn.DatabaseTests/DB2Tests.cs
@@ -1,9 +1,12 @@
-using IBM.Data.DB2.Core;
-using Shouldly;
+using Shouldly;
using System;
using System.Threading.Tasks;
+using DotNet.Testcontainers.Builders;
+using DotNet.Testcontainers.Images;
+using IBM.Data.Db2;
using NPoco;
using Respawn.Graph;
+using Testcontainers.Db2;
using Xunit;
using Xunit.Abstractions;
@@ -11,29 +14,36 @@ namespace Respawn.DatabaseTests
{
public class DB2Tests : IAsyncLifetime
{
+ private Db2Container _sqlContainer;
private DB2Connection _connection;
private readonly ITestOutputHelper _output;
- private const string _connectionString = "Server=127.0.0.1:50000;Database=SAMPLEDB;UID=db2inst1;PWD=password;Persist Security Info=True;Authentication=Server;";
-
public DB2Tests(ITestOutputHelper output)
{
_output = output;
}
- public Task DisposeAsync()
+ public async Task InitializeAsync()
{
- _connection?.Close();
- _connection?.Dispose();
- _connection = null;
- return Task.FromResult(0);
+ _sqlContainer = new Db2Builder()
+ .WithAcceptLicenseAgreement(true)
+ .Build();
+ await _sqlContainer.StartAsync();
+
+ _connection = new DB2Connection(_sqlContainer.GetConnectionString());
+
+ await _connection.OpenAsync();
}
- public async Task InitializeAsync()
+ public async Task DisposeAsync()
{
- _connection = new DB2Connection(_connectionString);
+ _connection?.Close();
+ _connection?.Dispose();
+ _connection = null;
- await _connection.OpenAsync();
+ await _sqlContainer.StopAsync();
+ await _sqlContainer.DisposeAsync();
+ _sqlContainer = null;
}
[SkipOnCI]
diff --git a/Respawn.DatabaseTests/EmptyDbTests.cs b/Respawn.DatabaseTests/EmptyDbTests.cs
index e3b0ae3..009a993 100644
--- a/Respawn.DatabaseTests/EmptyDbTests.cs
+++ b/Respawn.DatabaseTests/EmptyDbTests.cs
@@ -1,6 +1,7 @@
using System.Threading.Tasks;
using Microsoft.Data.SqlClient;
using Respawn.Graph;
+using Testcontainers.MsSql;
using Xunit;
using Xunit.Abstractions;
@@ -15,6 +16,7 @@ public class EmptyDbTests : IAsyncLifetime
{
private SqlConnection _connection;
private Database _database;
+ private MsSqlContainer _msSqlContainer;
public EmptyDbTests(ITestOutputHelper output)
@@ -23,7 +25,10 @@ public EmptyDbTests(ITestOutputHelper output)
public async Task InitializeAsync()
{
- var connString = @"Server=(LocalDb)\mssqllocaldb;Database=tempdb;Integrated Security=True";
+ _msSqlContainer = new MsSqlBuilder().Build();
+ await _msSqlContainer.StartAsync();
+
+ var connString = _msSqlContainer.GetConnectionString();
await using (var connection = new SqlConnection(connString))
{
@@ -35,10 +40,13 @@ public async Task InitializeAsync()
await database.ExecuteAsync("create database [EmptyDbTests]");
}
}
+
+ var newConnString = new SqlConnectionStringBuilder(connString)
+ {
+ InitialCatalog = "EmptyDbTests"
+ }.ConnectionString;
- connString = @"Server=(LocalDb)\mssqllocaldb;Database=EmptyDbTests;Integrated Security=True";
-
- _connection = new SqlConnection(connString);
+ _connection = new SqlConnection(newConnString);
_connection.Open();
_database = new Database(_connection);
diff --git a/Respawn.DatabaseTests/InformixTests.cs b/Respawn.DatabaseTests/InformixTests.cs
index a37a482..57e4380 100644
--- a/Respawn.DatabaseTests/InformixTests.cs
+++ b/Respawn.DatabaseTests/InformixTests.cs
@@ -1,11 +1,15 @@
//#if INFORMIX
-using IBM.Data.DB2.Core;
using Respawn;
using Shouldly;
using System;
using System.Data;
+using System.IO;
using System.Linq;
using System.Threading.Tasks;
+using DotNet.Testcontainers.Builders;
+using DotNet.Testcontainers.Configurations;
+using DotNet.Testcontainers.Containers;
+using IBM.Data.Db2;
using NPoco;
using Respawn.Graph;
using Xunit;
@@ -18,24 +22,76 @@ public class InformixTests : IAsyncLifetime
private DB2Connection _connection;
private readonly ITestOutputHelper _output;
private string _databaseName;
+ private IContainer _sqlContainer;
public InformixTests(ITestOutputHelper output)
{
_output = output;
}
- public Task DisposeAsync()
+ public async Task DisposeAsync()
{
_connection?.Close();
_connection?.Dispose();
_connection = null;
- return Task.FromResult(0);
+
+ await _sqlContainer.StopAsync();
+ await _sqlContainer.DisposeAsync();
+ _sqlContainer = null;
}
public async Task InitializeAsync()
{
- const string connString = "Server=127.0.0.1:9089;Database=sysadmin;UID=informix;PWD=in4mix;Persist Security Info=True;Authentication=Server;";
-
+ //const string connString = "Server=127.0.0.1:9089;Database=sysadmin;UID=informix;PWD=in4mix;Persist Security Info=True;Authentication=Server;";
+
+ _sqlContainer = new ContainerBuilder()
+ .WithImage("ibmcom/informix-developer-database:14.10.FC5DE")
+
+ // = environment:
+ .WithEnvironment("LICENSE", "accept")
+ .WithEnvironment("ONCONFIG_FILE", "onconfig")
+ .WithEnvironment("RUN_FILE_PRE_INIT", "my_post.sh")
+
+ // = ports:
+ .WithPortBinding(9088, 9088)
+ .WithPortBinding(9089, 9089)
+ .WithPortBinding(27017, 27017)
+ .WithPortBinding(27018, 27018)
+ .WithPortBinding(27883, 27883)
+
+ // = volumes:
+ .WithBindMount(
+ source: Path.GetFullPath("./informix-server"),
+ destination: "/opt/ibm/config",
+ AccessMode.ReadWrite)
+
+ // = privileged: true
+ .WithPrivileged(true)
+
+ // = user: root
+ //.WithUser("root")
+
+ // = tty: true
+ //.WithTty(true)
+
+ // optional: equivalent to "restart: always" but Testcontainers
+ // does not automatically restart containers (it recreates instead)
+ // .WithAutoRemove(false)
+
+ .WithWaitStrategy(Wait.ForUnixContainer()
+ .UntilExternalTcpPortIsAvailable(9088)
+ .UntilExternalTcpPortIsAvailable(9089)
+ .UntilInternalTcpPortIsAvailable(9088)
+ .UntilInternalTcpPortIsAvailable(9089)
+ // This is the last success message
+ .UntilMessageIsLogged("starting mqtt listener on port 27883")
+ )
+ .Build();
+
+ await _sqlContainer.StartAsync();
+
+ var connString = GetConnectionString(_sqlContainer);
+
await using (var connection = new DB2Connection(connString))
{
await connection.OpenAsync();
@@ -47,13 +103,33 @@ public async Task InitializeAsync()
await database.ExecuteAsync($"CREATE DATABASE {_databaseName} WITH BUFFERED LOG;");
}
- var testDbConnString = $"Server=127.0.0.1:9089;Database={_databaseName};UID=informix;PWD=in4mix;Persist Security Info=True;Authentication=Server;";
+ var testDbConnString = new DB2ConnectionStringBuilder(connString)
+ {
+ Database = _databaseName
+ }.ToString();
_connection = new DB2Connection(testDbConnString);
await _connection.OpenAsync();
}
+ private static string GetConnectionString(
+ IContainer container,
+ string database = "sysadmin",
+ string user = "informix",
+ string password = "in4mix")
+ {
+ var host = container.Hostname;
+ var port = container.GetMappedPublicPort(9089); // SQL port
+
+ return
+ $"Server={host}:{port};" +
+ $"Database={database};" +
+ $"UID={user};" +
+ $"Password={password};" +
+ $"Persist Security Info=True;Authentication=Server;";
+ }
+
[SkipOnCI]
public async Task ShouldDeleteData()
{
diff --git a/Respawn.DatabaseTests/MySqlTests.cs b/Respawn.DatabaseTests/MySqlTests.cs
index e0fbc8b..5ad306c 100644
--- a/Respawn.DatabaseTests/MySqlTests.cs
+++ b/Respawn.DatabaseTests/MySqlTests.cs
@@ -1,6 +1,7 @@
using System.Threading.Tasks;
using MySql.Data.MySqlClient;
using Respawn.Graph;
+using Testcontainers.MySql;
using Xunit;
using Xunit.Abstractions;
@@ -11,12 +12,13 @@ namespace Respawn.DatabaseTests
using NPoco;
using Shouldly;
- public class MySqlTests : IDisposable
+ public class MySqlTests : IAsyncLifetime
{
private readonly ITestOutputHelper _output;
private MySqlConnection _connection;
- private readonly IDatabase _database;
-
+ private IDatabase _database;
+ private MySqlContainer _sqlContainer;
+
public class Foo
{
public int Value { get; set; }
@@ -26,24 +28,35 @@ public class Bar
public int Value { get; set; }
}
- public MySqlTests(ITestOutputHelper output)
+
+ public async Task InitializeAsync()
{
- _output = output;
- var isCI = Environment.GetEnvironmentVariable("CI")?.ToUpperInvariant() == "TRUE";
-
- var connString =
- isCI
- ? @"Server=127.0.0.1; port = 3306; User Id = root; Password = Password12!"
- : @"Server=127.0.0.1; port = 8082; User Id = root; Password = testytest";
+ _sqlContainer = new MySqlBuilder()
+ .WithImage("mysql:8.0")
+ .WithDatabase("MySqlTests")
+ .Build();
+ await _sqlContainer.StartAsync();
+
+ var connString = _sqlContainer.GetConnectionString();
_connection = new MySqlConnection(connString);
_connection.Open();
_database = new Database(_connection);
+ }
- _database.Execute(@"DROP DATABASE IF EXISTS MySqlTests");
- _database.Execute("create database MySqlTests");
- _database.Execute("use MySqlTests");
+ public async Task DisposeAsync()
+ {
+ _connection?.Close();
+ _connection?.Dispose();
+ _connection = null;
+ await _sqlContainer.StopAsync();
+ await _sqlContainer.DisposeAsync();
+ }
+
+ public MySqlTests(ITestOutputHelper output)
+ {
+ _output = output;
}
[SkipOnCI]
@@ -364,5 +377,6 @@ public void Dispose()
_connection.Close();
_connection.Dispose();
}
+
}
}
diff --git a/Respawn.DatabaseTests/OracleTests.cs b/Respawn.DatabaseTests/OracleTests.cs
index eabde91..6da7a6e 100644
--- a/Respawn.DatabaseTests/OracleTests.cs
+++ b/Respawn.DatabaseTests/OracleTests.cs
@@ -1,4 +1,5 @@
-using Xunit.Abstractions;
+using Testcontainers.Oracle;
+using Xunit.Abstractions;
#if ORACLE
namespace Respawn.DatabaseTests
@@ -17,14 +18,15 @@ public class OracleTests : IAsyncLifetime
private OracleConnection _connection;
private Database _database;
private string _createdUser;
+ private OracleContainer _sqlContainer;
- public class foo
+ public class Foo
{
- public int value { get; set; }
+ public int Value { get; set; }
}
- public class bar
+ public class Bar
{
- public int value { get; set; }
+ public int Value { get; set; }
}
public OracleTests(ITestOutputHelper output)
@@ -35,14 +37,36 @@ public OracleTests(ITestOutputHelper output)
public async Task InitializeAsync()
{
_createdUser = Guid.NewGuid().ToString().Substring(0, 8);
- await CreateUser(_createdUser);
- _connection = new OracleConnection("Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=10521))(CONNECT_DATA=(SID=xe)));User Id=\"" + _createdUser + "\";Password=123456;");
+
+ _sqlContainer = new OracleBuilder()
+ .WithImage("gvenzl/oracle-xe:21.3.0-slim-faststart")
+ .WithUsername(_createdUser)
+ .Build();
+ await _sqlContainer.StartAsync();
+
+ var connString = _sqlContainer.GetConnectionString();
+
+ _connection = new OracleConnection(connString);
await _connection.OpenAsync();
_database = new Database(_connection, DatabaseType.OracleManaged);
}
+
+ public async Task DisposeAsync()
+ {
+ _database.Dispose();
+ _database = null;
+
+ _connection.Close();
+ _connection.Dispose();
+ _connection = null;
+
+ await _sqlContainer.StopAsync();
+ await _sqlContainer.DisposeAsync();
+ }
+
[SkipOnCI]
public async Task ShouldDeleteData()
{
@@ -463,9 +487,10 @@ public async Task ShouldIncludeSchemas()
await DropUser(userB);
}
- private static async Task CreateUser(string userName)
+ private async Task CreateUser(string userName)
{
- using (var connection = new OracleConnection("Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=10521))(CONNECT_DATA=(SID=xe)));User Id=system;Password=oracle;"))
+ var connString = _sqlContainer.GetConnectionString();
+ using (var connection = new OracleConnection(connString))
{
await connection.OpenAsync();
@@ -482,9 +507,10 @@ private static async Task CreateUser(string userName)
}
}
- private static async Task DropUser(string userName)
+ private async Task DropUser(string userName)
{
- using (var connection = new OracleConnection("Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=10521))(CONNECT_DATA=(SID=xe)));User Id=system;Password=oracle;"))
+ var connString = _sqlContainer.GetConnectionString();
+ using (var connection = new OracleConnection(connString))
{
await connection.OpenAsync();
@@ -509,20 +535,6 @@ private static async Task DropUser(string userName)
}
}
- public async Task DisposeAsync()
- {
- _database.Dispose();
- _database = null;
-
- OracleConnection.ClearPool(_connection);
-
- _connection.Close();
- _connection.Dispose();
- _connection = null;
-
- // Clean up our mess before leaving
- await DropUser(_createdUser);
- }
}
}
#endif
\ No newline at end of file
diff --git a/Respawn.DatabaseTests/PostgresTests.cs b/Respawn.DatabaseTests/PostgresTests.cs
index b2859ae..039f601 100644
--- a/Respawn.DatabaseTests/PostgresTests.cs
+++ b/Respawn.DatabaseTests/PostgresTests.cs
@@ -1,6 +1,7 @@
using System.Linq;
using System.Threading.Tasks;
using Respawn.Graph;
+using Testcontainers.PostgreSql;
using Xunit;
using Xunit.Abstractions;
@@ -16,41 +17,55 @@ public class PostgresTests : IAsyncLifetime
private readonly ITestOutputHelper _output;
private NpgsqlConnection _connection;
private Database _database;
+ private PostgreSqlContainer _sqlContainer;
public PostgresTests(ITestOutputHelper output) => _output = output;
public async Task InitializeAsync()
{
- var rootConnString = "Server=127.0.0.1;Port=8081;User ID=docker;Password=Password12!;database=postgres";
- var dbConnString = "Server=127.0.0.1;Port=8081;User ID=docker;Password=Password12!;database={0}";
- if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("CI")))
- {
- rootConnString = "Server=127.0.0.1;Port=5432;User ID=postgres;Password=root;database=postgres";
- dbConnString = "Server=127.0.0.1;Port=5432;User ID=postgres;Password=root;database={0}";
- }
+ // var rootConnString = "Server=127.0.0.1;Port=8081;User ID=docker;Password=Password12!;database=postgres";
+ // var dbConnString = "Server=127.0.0.1;Port=8081;User ID=docker;Password=Password12!;database={0}";
+ // if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("CI")))
+ // {
+ // rootConnString = "Server=127.0.0.1;Port=5432;User ID=postgres;Password=root;database=postgres";
+ // dbConnString = "Server=127.0.0.1;Port=5432;User ID=postgres;Password=root;database={0}";
+ // }
+ // var dbName = DateTime.Now.ToString("yyyyMMddHHmmss") + Guid.NewGuid().ToString("N");
+ // await using (var connection = new NpgsqlConnection(rootConnString))
+ // {
+ // connection.Open();
+ //
+ // await using (var cmd = connection.CreateCommand())
+ // {
+ // cmd.CommandText = "create database \"" + dbName + "\"";
+ // await cmd.ExecuteNonQueryAsync();
+ // }
+ // }
+
var dbName = DateTime.Now.ToString("yyyyMMddHHmmss") + Guid.NewGuid().ToString("N");
- await using (var connection = new NpgsqlConnection(rootConnString))
- {
- connection.Open();
-
- await using (var cmd = connection.CreateCommand())
- {
- cmd.CommandText = "create database \"" + dbName + "\"";
- await cmd.ExecuteNonQueryAsync();
- }
- }
- _connection = new NpgsqlConnection(string.Format(dbConnString, dbName));
+
+ _sqlContainer = new PostgreSqlBuilder()
+ .WithImage("postgres:16")
+ .WithDatabase(dbName)
+ .Build();
+
+ await _sqlContainer.StartAsync();
+
+ var dbConnString = _sqlContainer.GetConnectionString();
+
+ _connection = new NpgsqlConnection(dbConnString);
_connection.Open();
_database = new Database(_connection, DatabaseType.PostgreSQL);
}
- public Task DisposeAsync()
+ public async Task DisposeAsync()
{
_connection?.Close();
_connection?.Dispose();
_connection = null;
- return Task.FromResult(0);
+ await _sqlContainer.StopAsync();
+ await _sqlContainer.DisposeAsync();
}
[SkipOnCI]
diff --git a/Respawn.DatabaseTests/Respawn.DatabaseTests.csproj b/Respawn.DatabaseTests/Respawn.DatabaseTests.csproj
index 459dd48..0da14ac 100644
--- a/Respawn.DatabaseTests/Respawn.DatabaseTests.csproj
+++ b/Respawn.DatabaseTests/Respawn.DatabaseTests.csproj
@@ -5,23 +5,32 @@
$(NoWarn);NU1902;NU1903;NU1904
-
+
+
-
-
-
+
+
+
+
+
+
+
+
-
+
-
+
+ PreserveNewest
+
+
\ No newline at end of file
diff --git a/Respawn.DatabaseTests/SqlServerTests.cs b/Respawn.DatabaseTests/SqlServerTests.cs
index 8e1b2f2..7139438 100644
--- a/Respawn.DatabaseTests/SqlServerTests.cs
+++ b/Respawn.DatabaseTests/SqlServerTests.cs
@@ -1,6 +1,7 @@
using System.Threading.Tasks;
using Microsoft.Data.SqlClient;
using Respawn.Graph;
+using Testcontainers.MsSql;
using Xunit;
using Xunit.Abstractions;
@@ -16,6 +17,7 @@ public class SqlServerTests : IAsyncLifetime
private readonly ITestOutputHelper _output;
private SqlConnection _connection;
private Database _database;
+ private MsSqlContainer _sqlContainer;
public class Foo
{
@@ -49,7 +51,12 @@ public class Child
public async Task InitializeAsync()
{
- var connString = @"Server=(LocalDb)\mssqllocaldb;Database=tempdb;Integrated Security=True";
+ _sqlContainer = new MsSqlBuilder()
+ .WithImage("mcr.microsoft.com/mssql/server:2022-CU10-ubuntu-22.04")
+ .Build();
+ await _sqlContainer.StartAsync();
+
+ var connString = _sqlContainer.GetConnectionString();
await using (var connection = new SqlConnection(connString))
{
@@ -61,21 +68,25 @@ public async Task InitializeAsync()
await database.ExecuteAsync("create database [SqlServerTests]");
}
}
+
+ var newConnString = new SqlConnectionStringBuilder(connString)
+ {
+ InitialCatalog = "SqlServerTests"
+ }.ConnectionString;
- connString = @"Server=(LocalDb)\mssqllocaldb;Database=SqlServerTests;Integrated Security=True";
-
- _connection = new SqlConnection(connString);
+ _connection = new SqlConnection(newConnString);
_connection.Open();
_database = new Database(_connection);
}
- public Task DisposeAsync()
+ public async Task DisposeAsync()
{
_connection?.Close();
_connection?.Dispose();
_connection = null;
- return Task.FromResult(0);
+ await _sqlContainer.StopAsync();
+ await _sqlContainer.DisposeAsync();
}
[Fact]
@@ -272,7 +283,7 @@ public async Task ShouldHandleCircularRelationships()
{
await checkpoint.ResetAsync(_connection);
}
- catch
+ catch
{
_output.WriteLine(checkpoint.DeleteSql);
throw;
@@ -383,7 +394,7 @@ public async Task ShouldIncludeTables()
[Fact]
public async Task ShouldExcludeSchemas()
- {
+ {
await _database.ExecuteAsync("drop schema if exists A");
await _database.ExecuteAsync("drop schema if exists B");
await _database.ExecuteAsync("create schema A");
@@ -481,10 +492,10 @@ public async Task ShouldReseedId_TableWithSchema()
{
await _database.ExecuteAsync("IF EXISTS (SELECT * FROM sys.schemas WHERE name = 'A') DROP SCHEMA A");
await _database.ExecuteAsync("create schema A");
- await _database.ExecuteAsync("create table A.Foo ([id] [int] IDENTITY(1,1), Value int)");
-
- for (int i = 0; i < 100; i++)
- {
+ await _database.ExecuteAsync("create table A.Foo ([id] [int] IDENTITY(1,1), Value int)");
+
+ for (int i = 0; i < 100; i++)
+ {
await _database.ExecuteAsync("INSERT A.Foo VALUES (" + i + ")");
}
@@ -502,8 +513,8 @@ public async Task ShouldReseedId_TableWithSchema()
{
_output.WriteLine(checkpoint.ReseedSql);
throw;
- }
-
+ }
+
await _database.ExecuteAsync("INSERT A.Foo VALUES (0)");
_database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(1);
@@ -511,7 +522,7 @@ public async Task ShouldReseedId_TableWithSchema()
[Fact]
public async Task ShouldReseedId_TableHasNeverHadAnyData()
- {
+ {
await _database.ExecuteAsync("drop schema if exists A");
await _database.ExecuteAsync("create schema A");
await _database.ExecuteAsync("create table A.Foo ([id] [int] IDENTITY(1,1), Value int)");
@@ -527,12 +538,12 @@ public async Task ShouldReseedId_TableHasNeverHadAnyData()
{
_output.WriteLine(checkpoint.ReseedSql);
throw;
- }
-
+ }
+
await _database.ExecuteAsync("INSERT A.Foo VALUES (0)");
_database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(1);
- }
-
+ }
+
[Fact]
public async Task ShouldReseedId_TableWithSchemaHasNeverHadAnyData()
{
@@ -580,17 +591,17 @@ public async Task ShouldNotReseedId()
await _database.InsertAsync(new Foo { Value = 0 });
_database.ExecuteScalar("SELECT MAX(id) FROM Foo").ShouldBe(101);
- }
-
+ }
+
[Fact]
public async Task ShouldNotReseedId_TableWithSchema()
- {
+ {
await _database.ExecuteAsync("drop schema if exists A");
await _database.ExecuteAsync("create schema A");
- await _database.ExecuteAsync("create table A.Foo ([id] [int] IDENTITY(1,1), Value int)");
-
- for (int i = 0; i < 100; i++)
- {
+ await _database.ExecuteAsync("create table A.Foo ([id] [int] IDENTITY(1,1), Value int)");
+
+ for (int i = 0; i < 100; i++)
+ {
await _database.ExecuteAsync("INSERT A.Foo VALUES (" + i + ")");
}
@@ -608,8 +619,8 @@ public async Task ShouldNotReseedId_TableWithSchema()
{
_output.WriteLine(checkpoint.ReseedSql);
throw;
- }
-
+ }
+
await _database.ExecuteAsync("INSERT A.Foo VALUES (0)");
_database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(101);
}
@@ -643,14 +654,14 @@ public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue()
}
[Fact]
- public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue_TableWithSchema()
- {
+ public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue_TableWithSchema()
+ {
await _database.ExecuteAsync("drop schema if exists A");
- await _database.ExecuteAsync("create schema A");
- await _database.ExecuteAsync("create table A.Foo ([id] [int] IDENTITY(1001,1), Value int)");
-
- for (int i = 0; i < 100; i++)
- {
+ await _database.ExecuteAsync("create schema A");
+ await _database.ExecuteAsync("create table A.Foo ([id] [int] IDENTITY(1001,1), Value int)");
+
+ for (int i = 0; i < 100; i++)
+ {
await _database.ExecuteAsync("INSERT A.Foo VALUES (" + i + ")");
}
@@ -669,10 +680,10 @@ public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue_TableWithSch
{
_output.WriteLine(checkpoint.ReseedSql);
throw;
- }
-
+ }
+
await _database.ExecuteAsync("INSERT A.Foo VALUES (0)");
- _database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(1001);
+ _database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(1001);
}
[Fact]
@@ -697,11 +708,11 @@ public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue_TableHasNeve
await _database.InsertAsync(new Foo { Value = 0 });
_database.ExecuteScalar("SELECT MAX(id) FROM Foo").ShouldBe(1001);
- }
-
+ }
+
[Fact]
public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue_TableWithSchemaHasNeverHadAnyData()
- {
+ {
await _database.ExecuteAsync("drop schema if exists A");
await _database.ExecuteAsync("create schema A");
await _database.ExecuteAsync("create table A.Foo ([id] [int] IDENTITY(1001,1), Value int)");
@@ -719,8 +730,8 @@ public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue_TableWithSch
{
_output.WriteLine(checkpoint.ReseedSql);
throw;
- }
-
+ }
+
await _database.ExecuteAsync("INSERT A.Foo VALUES (0)");
_database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(1001);
}
@@ -808,13 +819,13 @@ FROM sys.tables t1
WHERE t1.object_id = (SELECT history_table_id FROM sys.tables t2 WHERE t2.name = 'Foo')
";
_database.ExecuteScalar(sql).ShouldStartWith("MSSQL_TemporalHistoryFor_");
- }
-
+ }
+
[Fact]
public async Task ShouldDeleteTemporalTablesDataFromNotDefaultSchemas()
{
- await _database.ExecuteAsync("CREATE SCHEMA [TableSchema] AUTHORIZATION [dbo];");
- await _database.ExecuteAsync("CREATE SCHEMA [HistorySchema] AUTHORIZATION [dbo];");
+ await _database.ExecuteAsync("CREATE SCHEMA [TableSchema] AUTHORIZATION [dbo];");
+ await _database.ExecuteAsync("CREATE SCHEMA [HistorySchema] AUTHORIZATION [dbo];");
await _database.ExecuteAsync("create table TableSchema.Foo (Value [int] not null primary key clustered, " +
"ValidFrom datetime2 generated always as row start, " +
diff --git a/Respawn/DB2DbAdapter.cs b/Respawn/DB2DbAdapter.cs
index cc031cf..96e357d 100644
--- a/Respawn/DB2DbAdapter.cs
+++ b/Respawn/DB2DbAdapter.cs
@@ -220,5 +220,10 @@ public Task CheckSupportsTemporalTables(DbConnection connection)
{
return Task.FromResult(false);
}
+
+ public bool RequiresStatementsToBeExecutedIndividually()
+ {
+ return false;
+ }
}
}
diff --git a/Respawn/Respawner.cs b/Respawn/Respawner.cs
index 24a25a8..5832d43 100644
--- a/Respawn/Respawner.cs
+++ b/Respawn/Respawner.cs
@@ -78,6 +78,9 @@ public virtual async Task ResetAsync(DbConnection connection)
try
{
+ if (Options.DbAdapter == null)
+ throw new InvalidOperationException("Database adapter is not set in options.");
+
if (Options.DbAdapter.RequiresStatementsToBeExecutedIndividually())
{
await ExecuteDeleteSqlIndividuallyAsync(connection).ConfigureAwait(false);
diff --git a/Respawn/SnowflakeDbAdapter.cs b/Respawn/SnowflakeDbAdapter.cs
index 027031e..cd6fa0d 100644
--- a/Respawn/SnowflakeDbAdapter.cs
+++ b/Respawn/SnowflakeDbAdapter.cs
@@ -103,7 +103,7 @@ public string BuildRelationshipCommandText(RespawnerOptions options)
return commandText;
}
- public string BuildDeleteCommandText(GraphBuilder graph)
+ public string BuildDeleteCommandText(GraphBuilder graph, RespawnerOptions options)
{
var builder = new StringBuilder();
diff --git a/Respawn/SqliteDbAdapter.cs b/Respawn/SqliteDbAdapter.cs
index c7c52cc..8afcfba 100644
--- a/Respawn/SqliteDbAdapter.cs
+++ b/Respawn/SqliteDbAdapter.cs
@@ -103,5 +103,10 @@ public Task CheckSupportsTemporalTables(DbConnection connection)
{
return Task.FromResult(false);
}
+
+ public bool RequiresStatementsToBeExecutedIndividually()
+ {
+ return false;
+ }
}
}