diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c3c238..8824f8c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,8 @@ on: jobs: build: strategy: + matrix: + os: [windows-latest] fail-fast: false runs-on: windows-latest steps: @@ -17,6 +19,10 @@ jobs: uses: actions/checkout@v2 with: fetch-depth: 0 + - name: Setup dotnet 6.0 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' - name: Build and Test run: ./Build.ps1 shell: pwsh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9a6c15a..57e92d9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,6 +7,8 @@ on: jobs: build: strategy: + matrix: + os: [windows-latest] fail-fast: false runs-on: windows-latest steps: @@ -14,6 +16,10 @@ jobs: uses: actions/checkout@v2 with: fetch-depth: 0 + - name: Setup dotnet 6.0 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.0.x' - name: Build and Test run: ./Build.ps1 shell: pwsh diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..2825fa0 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,7 @@ + + + 10.0 + $(NoWarn);CS1701;CS1702;CS1591 + true + + diff --git a/Respawn.DatabaseTests/MySqlTests.cs b/Respawn.DatabaseTests/MySqlTests.cs index 33affbc..3bd770a 100644 --- a/Respawn.DatabaseTests/MySqlTests.cs +++ b/Respawn.DatabaseTests/MySqlTests.cs @@ -372,7 +372,6 @@ public void Dispose() { _connection.Close(); _connection.Dispose(); - _connection = null; } } } diff --git a/Respawn.DatabaseTests/OracleTests.cs b/Respawn.DatabaseTests/OracleTests.cs index 36ec4d5..8a36314 100644 --- a/Respawn.DatabaseTests/OracleTests.cs +++ b/Respawn.DatabaseTests/OracleTests.cs @@ -1,6 +1,6 @@ using Xunit.Abstractions; -#if NET461 && ORACLE +#if ORACLE namespace Respawn.DatabaseTests { using System; diff --git a/Respawn.DatabaseTests/PostgresTests.cs b/Respawn.DatabaseTests/PostgresTests.cs index 7eda0c0c..4c24d53 100644 --- a/Respawn.DatabaseTests/PostgresTests.cs +++ b/Respawn.DatabaseTests/PostgresTests.cs @@ -28,11 +28,11 @@ public async Task InitializeAsync() 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"); - using (var connection = new NpgsqlConnection(rootConnString)) + await using (var connection = new NpgsqlConnection(rootConnString)) { connection.Open(); - using (var cmd = connection.CreateCommand()) + await using (var cmd = connection.CreateCommand()) { cmd.CommandText = "create database \"" + dbName + "\""; await cmd.ExecuteNonQueryAsync(); @@ -55,11 +55,11 @@ public Task DisposeAsync() [SkipOnCI] public async Task ShouldDeleteData() { - _database.Execute("create table \"foo\" (value int)"); + await _database.ExecuteAsync("create table \"foo\" (value int)"); for (int i = 0; i < 100; i++) { - _database.Execute("INSERT INTO \"foo\" VALUES (@0)", i); + await _database.ExecuteAsync("INSERT INTO \"foo\" VALUES (@0)", i); } _database.ExecuteScalar("SELECT COUNT(1) FROM \"foo\"").ShouldBe(100); @@ -76,13 +76,13 @@ public async Task ShouldDeleteData() [SkipOnCI] public async Task ShouldIgnoreTables() { - _database.Execute("create table foo (Value int)"); - _database.Execute("create table bar (Value int)"); + await _database.ExecuteAsync("create table foo (Value int)"); + await _database.ExecuteAsync("create table bar (Value int)"); for (int i = 0; i < 100; i++) { - _database.Execute("INSERT INTO \"foo\" VALUES (@0)", i); - _database.Execute("INSERT INTO \"bar\" VALUES (@0)", i); + await _database.ExecuteAsync("INSERT INTO \"foo\" VALUES (@0)", i); + await _database.ExecuteAsync("INSERT INTO \"bar\" VALUES (@0)", i); } var checkpoint = new Checkpoint @@ -99,13 +99,13 @@ public async Task ShouldIgnoreTables() [SkipOnCI] public async Task ShouldIncludeTables() { - _database.Execute("create table foo (Value int)"); - _database.Execute("create table bar (Value int)"); + await _database.ExecuteAsync("create table foo (Value int)"); + await _database.ExecuteAsync("create table bar (Value int)"); for (int i = 0; i < 100; i++) { - _database.Execute("INSERT INTO \"foo\" VALUES (@0)", i); - _database.Execute("INSERT INTO \"bar\" VALUES (@0)", i); + await _database.ExecuteAsync("INSERT INTO \"foo\" VALUES (@0)", i); + await _database.ExecuteAsync("INSERT INTO \"bar\" VALUES (@0)", i); } var checkpoint = new Checkpoint @@ -122,13 +122,13 @@ public async Task ShouldIncludeTables() [SkipOnCI] public async Task ShouldHandleRelationships() { - _database.Execute("create table foo (value int, primary key (value))"); - _database.Execute("create table baz (value int, foovalue int, constraint FK_Foo foreign key (foovalue) references foo (value))"); + await _database.ExecuteAsync("create table foo (value int, primary key (value))"); + await _database.ExecuteAsync("create table baz (value int, foovalue int, constraint FK_Foo foreign key (foovalue) references foo (value))"); for (int i = 0; i < 100; i++) { - _database.Execute("INSERT INTO \"foo\" VALUES (@0)", i); - _database.Execute("INSERT INTO \"baz\" VALUES (@0, @0)", i); + await _database.ExecuteAsync("INSERT INTO \"foo\" VALUES (@0)", i); + await _database.ExecuteAsync("INSERT INTO \"baz\" VALUES (@0, @0)", i); } _database.ExecuteScalar("SELECT COUNT(1) FROM foo").ShouldBe(100); @@ -156,19 +156,19 @@ public async Task ShouldHandleRelationships() [SkipOnCI] public async Task ShouldHandleCircularRelationships() { - _database.Execute("create table parent (id int primary key, childid int NULL)"); - _database.Execute("create table child (id int primary key, parentid int NULL)"); - _database.Execute("alter table parent add constraint FK_Child foreign key (ChildId) references Child (Id)"); - _database.Execute("alter table child add constraint FK_Parent foreign key (ParentId) references Parent (Id)"); + await _database.ExecuteAsync("create table parent (id int primary key, childid int NULL)"); + await _database.ExecuteAsync("create table child (id int primary key, parentid int NULL)"); + await _database.ExecuteAsync("alter table parent add constraint FK_Child foreign key (ChildId) references Child (Id)"); + await _database.ExecuteAsync("alter table child add constraint FK_Parent foreign key (ParentId) references Parent (Id)"); for (int i = 0; i < 100; i++) { - _database.Execute("INSERT INTO \"parent\" VALUES (@0, null)", i); - _database.Execute("INSERT INTO \"child\" VALUES (@0, null)", i); + await _database.ExecuteAsync("INSERT INTO \"parent\" VALUES (@0, null)", i); + await _database.ExecuteAsync("INSERT INTO \"child\" VALUES (@0, null)", i); } - _database.Execute("update parent set childid = 0"); - _database.Execute("update child set parentid = 1"); + await _database.ExecuteAsync("update parent set childid = 0"); + await _database.ExecuteAsync("update child set parentid = 1"); _database.ExecuteScalar("SELECT COUNT(1) FROM parent").ShouldBe(100); _database.ExecuteScalar("SELECT COUNT(1) FROM child").ShouldBe(100); @@ -194,13 +194,13 @@ public async Task ShouldHandleCircularRelationships() [SkipOnCI] public async Task ShouldHandleSelfRelationships() { - _database.Execute("create table foo (id int primary key, parentid int NULL)"); - _database.Execute("alter table foo add constraint FK_Parent foreign key (parentid) references foo (id)"); + await _database.ExecuteAsync("create table foo (id int primary key, parentid int NULL)"); + await _database.ExecuteAsync("alter table foo add constraint FK_Parent foreign key (parentid) references foo (id)"); - _database.Execute("INSERT INTO \"foo\" VALUES (@0)", 1); + await _database.ExecuteAsync("INSERT INTO \"foo\" VALUES (@0)", 1); for (int i = 1; i < 100; i++) { - _database.Execute("INSERT INTO \"foo\" VALUES (@0, @1)", i+1, i); + await _database.ExecuteAsync("INSERT INTO \"foo\" VALUES (@0, @1)", i+1, i); } _database.ExecuteScalar("SELECT COUNT(1) FROM foo").ShouldBe(100); @@ -225,29 +225,29 @@ public async Task ShouldHandleSelfRelationships() [SkipOnCI] public async Task ShouldHandleComplexCycles() { - _database.Execute("create table a (id int primary key, b_id int NULL)"); - _database.Execute("create table b (id int primary key, a_id int NULL, c_id int NULL, d_id int NULL)"); - _database.Execute("create table c (id int primary key, d_id int NULL)"); - _database.Execute("create table d (id int primary key)"); - _database.Execute("create table e (id int primary key, a_id int NULL)"); - _database.Execute("create table f (id int primary key, b_id int NULL)"); - _database.Execute("alter table a add constraint FK_a_b foreign key (b_id) references b (id)"); - _database.Execute("alter table b add constraint FK_b_a foreign key (a_id) references a (id)"); - _database.Execute("alter table b add constraint FK_b_c foreign key (c_id) references c (id)"); - _database.Execute("alter table b add constraint FK_b_d foreign key (d_id) references d (id)"); - _database.Execute("alter table c add constraint FK_c_d foreign key (d_id) references d (id)"); - _database.Execute("alter table e add constraint FK_e_a foreign key (a_id) references a (id)"); - _database.Execute("alter table f add constraint FK_f_b foreign key (b_id) references b (id)"); - - - _database.Execute("insert into d (id) values (1)"); - _database.Execute("insert into c (id, d_id) values (1, 1)"); - _database.Execute("insert into a (id) values (1)"); - _database.Execute("insert into b (id, c_id, d_id) values (1, 1, 1)"); - _database.Execute("insert into e (id, a_id) values (1, 1)"); - _database.Execute("insert into f (id, b_id) values (1, 1)"); - _database.Execute("update a set b_id = 1"); - _database.Execute("update b set a_id = 1"); + await _database.ExecuteAsync("create table a (id int primary key, b_id int NULL)"); + await _database.ExecuteAsync("create table b (id int primary key, a_id int NULL, c_id int NULL, d_id int NULL)"); + await _database.ExecuteAsync("create table c (id int primary key, d_id int NULL)"); + await _database.ExecuteAsync("create table d (id int primary key)"); + await _database.ExecuteAsync("create table e (id int primary key, a_id int NULL)"); + await _database.ExecuteAsync("create table f (id int primary key, b_id int NULL)"); + await _database.ExecuteAsync("alter table a add constraint FK_a_b foreign key (b_id) references b (id)"); + await _database.ExecuteAsync("alter table b add constraint FK_b_a foreign key (a_id) references a (id)"); + await _database.ExecuteAsync("alter table b add constraint FK_b_c foreign key (c_id) references c (id)"); + await _database.ExecuteAsync("alter table b add constraint FK_b_d foreign key (d_id) references d (id)"); + await _database.ExecuteAsync("alter table c add constraint FK_c_d foreign key (d_id) references d (id)"); + await _database.ExecuteAsync("alter table e add constraint FK_e_a foreign key (a_id) references a (id)"); + await _database.ExecuteAsync("alter table f add constraint FK_f_b foreign key (b_id) references b (id)"); + + + await _database.ExecuteAsync("insert into d (id) values (1)"); + await _database.ExecuteAsync("insert into c (id, d_id) values (1, 1)"); + await _database.ExecuteAsync("insert into a (id) values (1)"); + await _database.ExecuteAsync("insert into b (id, c_id, d_id) values (1, 1, 1)"); + await _database.ExecuteAsync("insert into e (id, a_id) values (1, 1)"); + await _database.ExecuteAsync("insert into f (id, b_id) values (1, 1)"); + await _database.ExecuteAsync("update a set b_id = 1"); + await _database.ExecuteAsync("update b set a_id = 1"); _database.ExecuteScalar("SELECT COUNT(1) FROM a").ShouldBe(1); _database.ExecuteScalar("SELECT COUNT(1) FROM b").ShouldBe(1); @@ -282,15 +282,15 @@ public async Task ShouldHandleComplexCycles() [SkipOnCI] public async Task ShouldExcludeSchemas() { - _database.Execute("create schema a"); - _database.Execute("create schema b"); - _database.Execute("create table a.foo (value int)"); - _database.Execute("create table b.bar (value int)"); + await _database.ExecuteAsync("create schema a"); + await _database.ExecuteAsync("create schema b"); + await _database.ExecuteAsync("create table a.foo (value int)"); + await _database.ExecuteAsync("create table b.bar (value int)"); for (int i = 0; i < 100; i++) { - _database.Execute("INSERT INTO a.foo VALUES (" + i + ")"); - _database.Execute("INSERT INTO b.bar VALUES (" + i + ")"); + await _database.ExecuteAsync("INSERT INTO a.foo VALUES (" + i + ")"); + await _database.ExecuteAsync("INSERT INTO b.bar VALUES (" + i + ")"); } var checkpoint = new Checkpoint @@ -307,15 +307,15 @@ public async Task ShouldExcludeSchemas() [SkipOnCI] public async Task ShouldIncludeSchemas() { - _database.Execute("create schema a"); - _database.Execute("create schema b"); - _database.Execute("create table a.foo (value int)"); - _database.Execute("create table b.bar (value int)"); + await _database.ExecuteAsync("create schema a"); + await _database.ExecuteAsync("create schema b"); + await _database.ExecuteAsync("create table a.foo (value int)"); + await _database.ExecuteAsync("create table b.bar (value int)"); for (int i = 0; i < 100; i++) { - _database.Execute("INSERT INTO a.foo VALUES (" + i + ")"); - _database.Execute("INSERT INTO b.bar VALUES (" + i + ")"); + await _database.ExecuteAsync("INSERT INTO a.foo VALUES (" + i + ")"); + await _database.ExecuteAsync("INSERT INTO b.bar VALUES (" + i + ")"); } var checkpoint = new Checkpoint @@ -332,10 +332,10 @@ public async Task ShouldIncludeSchemas() [SkipOnCI] public async Task ShouldResetSequencesAndIdentities() { - _database.Execute("CREATE TABLE a (id INT GENERATED ALWAYS AS IDENTITY, value SERIAL)"); - _database.Execute("INSERT INTO a DEFAULT VALUES"); - _database.Execute("INSERT INTO a DEFAULT VALUES"); - _database.Execute("INSERT INTO a DEFAULT VALUES"); + await _database.ExecuteAsync("CREATE TABLE a (id INT GENERATED ALWAYS AS IDENTITY, value SERIAL)"); + await _database.ExecuteAsync("INSERT INTO a DEFAULT VALUES"); + await _database.ExecuteAsync("INSERT INTO a DEFAULT VALUES"); + await _database.ExecuteAsync("INSERT INTO a DEFAULT VALUES"); var checkpoint = new Checkpoint { diff --git a/Respawn.DatabaseTests/Respawn.DatabaseTests.csproj b/Respawn.DatabaseTests/Respawn.DatabaseTests.csproj index 5165e3a..ad174c8 100644 --- a/Respawn.DatabaseTests/Respawn.DatabaseTests.csproj +++ b/Respawn.DatabaseTests/Respawn.DatabaseTests.csproj @@ -1,25 +1,19 @@  - net461;netcoreapp3.1 + net6.0 - - - - + + + + - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - + + + + diff --git a/Respawn.DatabaseTests/SqlServerTests.cs b/Respawn.DatabaseTests/SqlServerTests.cs index ecb4271..4e41bf0 100644 --- a/Respawn.DatabaseTests/SqlServerTests.cs +++ b/Respawn.DatabaseTests/SqlServerTests.cs @@ -1,11 +1,11 @@ using System.Threading.Tasks; +using Microsoft.Data.SqlClient; using Xunit; using Xunit.Abstractions; namespace Respawn.DatabaseTests { using System; - using System.Data.SqlClient; using System.Linq; using NPoco; using Shouldly; @@ -50,7 +50,7 @@ public async Task InitializeAsync() { var connString = @"Server=(LocalDb)\mssqllocaldb;Database=tempdb;Integrated Security=True"; - using (var connection = new SqlConnection(connString)) + await using (var connection = new SqlConnection(connString)) { await connection.OpenAsync(); using (var database = new Database(connection)) @@ -80,9 +80,9 @@ public Task DisposeAsync() [Fact] public async Task ShouldDeleteData() { - _database.Execute("create table Foo (Value [int])"); + await _database.ExecuteAsync("create table Foo (Value [int])"); - _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); + await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); _database.ExecuteScalar("SELECT COUNT(1) FROM Foo").ShouldBe(100); @@ -103,11 +103,11 @@ public async Task ShouldDeleteData() [Fact] public async Task ShouldHandleRelationships() { - _database.Execute("create table Foo (Value [int], constraint PK_Foo primary key nonclustered (value))"); - _database.Execute("create table Baz (Value [int], FooValue [int], constraint FK_Foo foreign key (FooValue) references Foo (Value))"); + await _database.ExecuteAsync("create table Foo (Value [int], constraint PK_Foo primary key nonclustered (value))"); + await _database.ExecuteAsync("create table Baz (Value [int], FooValue [int], constraint FK_Foo foreign key (FooValue) references Foo (Value))"); - _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); - _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Baz { Value = i, FooValue = i })); + await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); + await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Baz { Value = i, FooValue = i })); _database.ExecuteScalar("SELECT COUNT(1) FROM Foo").ShouldBe(100); _database.ExecuteScalar("SELECT COUNT(1) FROM Baz").ShouldBe(100); @@ -130,13 +130,13 @@ public async Task ShouldHandleRelationships() [Fact] public async Task ShouldHandleSelfRelationships() { - _database.Execute("create table circle (id int primary key, parentid int NULL)"); - _database.Execute("alter table circle add constraint FK_Parent foreign key (parentid) references circle (id)"); + await _database.ExecuteAsync("create table circle (id int primary key, parentid int NULL)"); + await _database.ExecuteAsync("alter table circle add constraint FK_Parent foreign key (parentid) references circle (id)"); - _database.Execute("INSERT INTO \"circle\" (id) VALUES (@0)", 1); + await _database.ExecuteAsync("INSERT INTO \"circle\" (id) VALUES (@0)", 1); for (int i = 1; i < 100; i++) { - _database.Execute("INSERT INTO \"circle\" (id, parentid) VALUES (@0, @1)", i + 1, i); + await _database.ExecuteAsync("INSERT INTO \"circle\" (id, parentid) VALUES (@0, @1)", i + 1, i); } _database.ExecuteScalar("SELECT COUNT(1) FROM circle").ShouldBe(100); @@ -158,29 +158,29 @@ public async Task ShouldHandleSelfRelationships() [Fact] public async Task ShouldHandleComplexCycles() { - _database.Execute("create table a (id int primary key, b_id int NULL)"); - _database.Execute("create table b (id int primary key, a_id int NULL, c_id int NULL, d_id int NULL)"); - _database.Execute("create table c (id int primary key, d_id int NULL)"); - _database.Execute("create table d (id int primary key)"); - _database.Execute("create table e (id int primary key, a_id int NULL)"); - _database.Execute("create table f (id int primary key, b_id int NULL)"); - _database.Execute("alter table a add constraint FK_a_b foreign key (b_id) references b (id)"); - _database.Execute("alter table b add constraint FK_b_a foreign key (a_id) references a (id)"); - _database.Execute("alter table b add constraint FK_b_c foreign key (c_id) references c (id)"); - _database.Execute("alter table b add constraint FK_b_d foreign key (d_id) references d (id)"); - _database.Execute("alter table c add constraint FK_c_d foreign key (d_id) references d (id)"); - _database.Execute("alter table e add constraint FK_e_a foreign key (a_id) references a (id)"); - _database.Execute("alter table f add constraint FK_f_b foreign key (b_id) references b (id)"); - - - _database.Execute("insert into d (id) values (1)"); - _database.Execute("insert into c (id, d_id) values (1, 1)"); - _database.Execute("insert into a (id) values (1)"); - _database.Execute("insert into b (id, c_id, d_id) values (1, 1, 1)"); - _database.Execute("insert into e (id, a_id) values (1, 1)"); - _database.Execute("insert into f (id, b_id) values (1, 1)"); - _database.Execute("update a set b_id = 1"); - _database.Execute("update b set a_id = 1"); + await _database.ExecuteAsync("create table a (id int primary key, b_id int NULL)"); + await _database.ExecuteAsync("create table b (id int primary key, a_id int NULL, c_id int NULL, d_id int NULL)"); + await _database.ExecuteAsync("create table c (id int primary key, d_id int NULL)"); + await _database.ExecuteAsync("create table d (id int primary key)"); + await _database.ExecuteAsync("create table e (id int primary key, a_id int NULL)"); + await _database.ExecuteAsync("create table f (id int primary key, b_id int NULL)"); + await _database.ExecuteAsync("alter table a add constraint FK_a_b foreign key (b_id) references b (id)"); + await _database.ExecuteAsync("alter table b add constraint FK_b_a foreign key (a_id) references a (id)"); + await _database.ExecuteAsync("alter table b add constraint FK_b_c foreign key (c_id) references c (id)"); + await _database.ExecuteAsync("alter table b add constraint FK_b_d foreign key (d_id) references d (id)"); + await _database.ExecuteAsync("alter table c add constraint FK_c_d foreign key (d_id) references d (id)"); + await _database.ExecuteAsync("alter table e add constraint FK_e_a foreign key (a_id) references a (id)"); + await _database.ExecuteAsync("alter table f add constraint FK_f_b foreign key (b_id) references b (id)"); + + + await _database.ExecuteAsync("insert into d (id) values (1)"); + await _database.ExecuteAsync("insert into c (id, d_id) values (1, 1)"); + await _database.ExecuteAsync("insert into a (id) values (1)"); + await _database.ExecuteAsync("insert into b (id, c_id, d_id) values (1, 1, 1)"); + await _database.ExecuteAsync("insert into e (id, a_id) values (1, 1)"); + await _database.ExecuteAsync("insert into f (id, b_id) values (1, 1)"); + await _database.ExecuteAsync("update a set b_id = 1"); + await _database.ExecuteAsync("update b set a_id = 1"); _database.ExecuteScalar("SELECT COUNT(1) FROM a").ShouldBe(1); _database.ExecuteScalar("SELECT COUNT(1) FROM b").ShouldBe(1); @@ -211,16 +211,16 @@ public async Task ShouldHandleComplexCycles() [Fact] public async Task ShouldHandleCircularRelationships() { - _database.Execute("create table Parent (Id [int] NOT NULL, ChildId [int] NULL, constraint PK_Parent primary key clustered (Id))"); - _database.Execute("create table Child (Id [int] NOT NULL, ParentId [int] NULL, constraint PK_Child primary key clustered (Id))"); - _database.Execute("alter table Parent add constraint FK_Child foreign key (ChildId) references Child (Id)"); - _database.Execute("alter table Child add constraint FK_Parent foreign key (ParentId) references Parent (Id)"); + await _database.ExecuteAsync("create table Parent (Id [int] NOT NULL, ChildId [int] NULL, constraint PK_Parent primary key clustered (Id))"); + await _database.ExecuteAsync("create table Child (Id [int] NOT NULL, ParentId [int] NULL, constraint PK_Child primary key clustered (Id))"); + await _database.ExecuteAsync("alter table Parent add constraint FK_Child foreign key (ChildId) references Child (Id)"); + await _database.ExecuteAsync("alter table Child add constraint FK_Parent foreign key (ParentId) references Parent (Id)"); - _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Parent { Id = i, ChildId = null })); - _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Child { Id = i, ParentId = null })); + await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Parent { Id = i, ChildId = null })); + await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Child { Id = i, ParentId = null })); - _database.Execute("update Parent set ChildId = 0"); - _database.Execute("update Child set ParentId = 1"); + await _database.ExecuteAsync("update Parent set ChildId = 0"); + await _database.ExecuteAsync("update Child set ParentId = 1"); _database.ExecuteScalar("SELECT COUNT(1) FROM Parent").ShouldBe(100); _database.ExecuteScalar("SELECT COUNT(1) FROM Child").ShouldBe(100); @@ -243,11 +243,11 @@ public async Task ShouldHandleCircularRelationships() [Fact] public async Task ShouldIgnoreTables() { - _database.Execute("create table Foo (Value [int])"); - _database.Execute("create table Bar (Value [int])"); + await _database.ExecuteAsync("create table Foo (Value [int])"); + await _database.ExecuteAsync("create table Bar (Value [int])"); - _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); - _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Bar { Value = i })); + await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); + await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Bar { Value = i })); var checkpoint = new Checkpoint { @@ -270,11 +270,11 @@ public async Task ShouldIgnoreTables() [Fact] public async Task ShouldIncludeTables() { - _database.Execute("create table Foo (Value [int])"); - _database.Execute("create table Bar (Value [int])"); + await _database.ExecuteAsync("create table Foo (Value [int])"); + await _database.ExecuteAsync("create table Bar (Value [int])"); - _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); - _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Bar { Value = i })); + await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); + await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Bar { Value = i })); var checkpoint = new Checkpoint { @@ -297,17 +297,17 @@ public async Task ShouldIncludeTables() [Fact] public async Task ShouldExcludeSchemas() { - _database.Execute("drop schema if exists A"); - _database.Execute("drop schema if exists B"); - _database.Execute("create schema A"); - _database.Execute("create schema B"); - _database.Execute("create table A.Foo (Value [int])"); - _database.Execute("create table B.Bar (Value [int])"); + await _database.ExecuteAsync("drop schema if exists A"); + await _database.ExecuteAsync("drop schema if exists B"); + await _database.ExecuteAsync("create schema A"); + await _database.ExecuteAsync("create schema B"); + await _database.ExecuteAsync("create table A.Foo (Value [int])"); + await _database.ExecuteAsync("create table B.Bar (Value [int])"); for (int i = 0; i < 100; i++) { - _database.Execute("INSERT A.Foo VALUES (" + i + ")"); - _database.Execute("INSERT B.Bar VALUES (" + i + ")"); + await _database.ExecuteAsync("INSERT A.Foo VALUES (" + i + ")"); + await _database.ExecuteAsync("INSERT B.Bar VALUES (" + i + ")"); } var checkpoint = new Checkpoint @@ -331,17 +331,17 @@ public async Task ShouldExcludeSchemas() [Fact] public async Task ShouldIncludeSchemas() { - _database.Execute("drop schema if exists A"); - _database.Execute("drop schema if exists B"); - _database.Execute("create schema A"); - _database.Execute("create schema B"); - _database.Execute("create table A.Foo (Value [int])"); - _database.Execute("create table B.Bar (Value [int])"); + await _database.ExecuteAsync("drop schema if exists A"); + await _database.ExecuteAsync("drop schema if exists B"); + await _database.ExecuteAsync("create schema A"); + await _database.ExecuteAsync("create schema B"); + await _database.ExecuteAsync("create table A.Foo (Value [int])"); + await _database.ExecuteAsync("create table B.Bar (Value [int])"); for (int i = 0; i < 100; i++) { - _database.Execute("INSERT A.Foo VALUES (" + i + ")"); - _database.Execute("INSERT B.Bar VALUES (" + i + ")"); + await _database.ExecuteAsync("INSERT A.Foo VALUES (" + i + ")"); + await _database.ExecuteAsync("INSERT B.Bar VALUES (" + i + ")"); } var checkpoint = new Checkpoint @@ -365,14 +365,16 @@ public async Task ShouldIncludeSchemas() [Fact] public async Task ShouldReseedId() { - _database.Execute("create table Foo ([id] [int] IDENTITY(1,1), Value int)"); + await _database.ExecuteAsync("create table Foo ([id] [int] IDENTITY(1,1), Value int)"); - _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); + await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); _database.ExecuteScalar("SELECT MAX(id) FROM Foo").ShouldBe(100); - var checkpoint = new Checkpoint(); - checkpoint.WithReseed = true; + var checkpoint = new Checkpoint + { + WithReseed = true + }; try { await checkpoint.Reset(_connection); @@ -383,26 +385,28 @@ public async Task ShouldReseedId() throw; } - _database.Insert(new Foo {Value = 0}); + await _database.InsertAsync(new Foo {Value = 0}); _database.ExecuteScalar("SELECT MAX(id) FROM Foo").ShouldBe(1); } [Fact] public async Task ShouldReseedId_TableWithSchema() { - _database.Execute("IF EXISTS (SELECT * FROM sys.schemas WHERE name = 'A') DROP SCHEMA A"); - _database.Execute("create schema A"); - _database.Execute("create table A.Foo ([id] [int] IDENTITY(1,1), Value int)"); + 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++) { - _database.Execute("INSERT A.Foo VALUES (" + i + ")"); + await _database.ExecuteAsync("INSERT A.Foo VALUES (" + i + ")"); } _database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(100); - var checkpoint = new Checkpoint(); - checkpoint.WithReseed = true; + var checkpoint = new Checkpoint + { + WithReseed = true + }; try { await checkpoint.Reset(_connection); @@ -413,7 +417,7 @@ public async Task ShouldReseedId_TableWithSchema() throw; } - _database.Execute("INSERT A.Foo VALUES (0)"); + await _database.ExecuteAsync("INSERT A.Foo VALUES (0)"); _database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(1); } @@ -421,11 +425,13 @@ public async Task ShouldReseedId_TableWithSchema() [Fact] public async Task ShouldReseedId_TableHasNeverHadAnyData() { - _database.Execute("drop schema if exists A"); - _database.Execute("create schema A"); - _database.Execute("create table A.Foo ([id] [int] IDENTITY(1,1), Value int)"); - var checkpoint = new Checkpoint(); - checkpoint.WithReseed = true; + 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)"); + var checkpoint = new Checkpoint + { + WithReseed = true + }; try { await checkpoint.Reset(_connection); @@ -436,16 +442,18 @@ public async Task ShouldReseedId_TableHasNeverHadAnyData() throw; } - _database.Execute("INSERT A.Foo VALUES (0)"); + await _database.ExecuteAsync("INSERT A.Foo VALUES (0)"); _database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(1); } [Fact] public async Task ShouldReseedId_TableWithSchemaHasNeverHadAnyData() { - _database.Execute("create table Foo ([id] [int] IDENTITY(1,1), Value int)"); - var checkpoint = new Checkpoint(); - checkpoint.WithReseed = true; + await _database.ExecuteAsync("create table Foo ([id] [int] IDENTITY(1,1), Value int)"); + var checkpoint = new Checkpoint + { + WithReseed = true + }; try { await checkpoint.Reset(_connection); @@ -456,21 +464,23 @@ public async Task ShouldReseedId_TableWithSchemaHasNeverHadAnyData() throw; } - _database.Insert(new Foo { Value = 0 }); + await _database.InsertAsync(new Foo { Value = 0 }); _database.ExecuteScalar("SELECT MAX(id) FROM Foo").ShouldBe(1); } [Fact] public async Task ShouldNotReseedId() { - _database.Execute("create table Foo ([id] [int] IDENTITY(1,1), Value int)"); + await _database.ExecuteAsync("create table Foo ([id] [int] IDENTITY(1,1), Value int)"); - _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); + await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); _database.ExecuteScalar("SELECT MAX(id) FROM Foo").ShouldBe(100); - var checkpoint = new Checkpoint(); - checkpoint.WithReseed = false; + var checkpoint = new Checkpoint + { + WithReseed = false + }; try { await checkpoint.Reset(_connection); @@ -481,26 +491,28 @@ public async Task ShouldNotReseedId() throw; } - _database.Insert(new Foo { Value = 0 }); + await _database.InsertAsync(new Foo { Value = 0 }); _database.ExecuteScalar("SELECT MAX(id) FROM Foo").ShouldBe(101); } [Fact] public async Task ShouldNotReseedId_TableWithSchema() { - _database.Execute("drop schema if exists A"); - _database.Execute("create schema A"); - _database.Execute("create table A.Foo ([id] [int] IDENTITY(1,1), Value int)"); + 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++) { - _database.Execute("INSERT A.Foo VALUES (" + i + ")"); + await _database.ExecuteAsync("INSERT A.Foo VALUES (" + i + ")"); } _database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(100); - var checkpoint = new Checkpoint(); - checkpoint.WithReseed = false; + var checkpoint = new Checkpoint + { + WithReseed = false + }; try { await checkpoint.Reset(_connection); @@ -511,21 +523,23 @@ public async Task ShouldNotReseedId_TableWithSchema() throw; } - _database.Execute("INSERT A.Foo VALUES (0)"); + await _database.ExecuteAsync("INSERT A.Foo VALUES (0)"); _database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(101); } [Fact] public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue() { - _database.Execute("create table Foo ([id] [int] IDENTITY(1001,1), Value int)"); + await _database.ExecuteAsync("create table Foo ([id] [int] IDENTITY(1001,1), Value int)"); - _database.InsertBulk(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); + await _database.InsertBulkAsync(Enumerable.Range(0, 100).Select(i => new Foo { Value = i })); _database.ExecuteScalar("SELECT MAX(id) FROM Foo").ShouldBe(1100); - var checkpoint = new Checkpoint(); - checkpoint.WithReseed = true; + var checkpoint = new Checkpoint + { + WithReseed = true + }; try { @@ -537,26 +551,28 @@ public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue() throw; } - _database.Insert(new Foo { Value = 0 }); + await _database.InsertAsync(new Foo { Value = 0 }); _database.ExecuteScalar("SELECT MAX(id) FROM Foo").ShouldBe(1001); } [Fact] public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue_TableWithSchema() { - _database.Execute("drop schema if exists A"); - _database.Execute("create schema A"); - _database.Execute("create table A.Foo ([id] [int] IDENTITY(1001,1), Value int)"); + 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++) { - _database.Execute("INSERT A.Foo VALUES (" + i + ")"); + await _database.ExecuteAsync("INSERT A.Foo VALUES (" + i + ")"); } _database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(1100); - var checkpoint = new Checkpoint(); - checkpoint.WithReseed = true; + var checkpoint = new Checkpoint + { + WithReseed = true + }; try { @@ -568,17 +584,19 @@ public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue_TableWithSch throw; } - _database.Execute("INSERT A.Foo VALUES (0)"); + await _database.ExecuteAsync("INSERT A.Foo VALUES (0)"); _database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(1001); } [Fact] public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue_TableHasNeverHadAnyData() { - _database.Execute("create table Foo ([id] [int] IDENTITY(1001,1), Value int)"); + await _database.ExecuteAsync("create table Foo ([id] [int] IDENTITY(1001,1), Value int)"); - var checkpoint = new Checkpoint(); - checkpoint.WithReseed = true; + var checkpoint = new Checkpoint + { + WithReseed = true + }; try { @@ -590,19 +608,21 @@ public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue_TableHasNeve throw; } - _database.Insert(new Foo { Value = 0 }); + await _database.InsertAsync(new Foo { Value = 0 }); _database.ExecuteScalar("SELECT MAX(id) FROM Foo").ShouldBe(1001); } [Fact] public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue_TableWithSchemaHasNeverHadAnyData() { - _database.Execute("drop schema if exists A"); - _database.Execute("create schema A"); - _database.Execute("create table A.Foo ([id] [int] IDENTITY(1001,1), Value int)"); - - var checkpoint = new Checkpoint(); - checkpoint.WithReseed = true; + 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)"); + + var checkpoint = new Checkpoint + { + WithReseed = true + }; try { @@ -614,28 +634,30 @@ public async Task ShouldReseedIdAccordingToIdentityInitialSeedValue_TableWithSch throw; } - _database.Execute("INSERT A.Foo VALUES (0)"); + await _database.ExecuteAsync("INSERT A.Foo VALUES (0)"); _database.ExecuteScalar("SELECT MAX(id) FROM A.Foo").ShouldBe(1001); } [Fact] public async Task ShouldDeleteTemporalTablesData() { - _database.Execute("drop table if exists FooHistory"); - _database.Execute("IF OBJECT_ID(N'Foo', N'U') IS NOT NULL alter table Foo set (SYSTEM_VERSIONING = OFF)"); - _database.Execute("drop table if exists Foo"); + await _database.ExecuteAsync("drop table if exists FooHistory"); + await _database.ExecuteAsync("IF OBJECT_ID(N'Foo', N'U') IS NOT NULL alter table Foo set (SYSTEM_VERSIONING = OFF)"); + await _database.ExecuteAsync("drop table if exists Foo"); - _database.Execute("create table Foo (Value [int] not null primary key clustered, " + - "ValidFrom datetime2 generated always as row start, " + - "ValidTo datetime2 generated always as row end," + - " period for system_time(ValidFrom, ValidTo)" + - ") with (system_versioning = on (history_table = dbo.FooHistory))"); + await _database.ExecuteAsync("create table Foo (Value [int] not null primary key clustered, " + + "ValidFrom datetime2 generated always as row start, " + + "ValidTo datetime2 generated always as row end," + + " period for system_time(ValidFrom, ValidTo)" + + ") with (system_versioning = on (history_table = dbo.FooHistory))"); - _database.Execute("INSERT Foo (Value) VALUES (1)"); - _database.Execute("UPDATE Foo SET Value = 2 Where Value = 1"); + await _database.ExecuteAsync("INSERT Foo (Value) VALUES (1)"); + await _database.ExecuteAsync("UPDATE Foo SET Value = 2 Where Value = 1"); - var checkpoint = new Checkpoint(); - checkpoint.CheckTemporalTables = true; + var checkpoint = new Checkpoint + { + CheckTemporalTables = true + }; await checkpoint.Reset(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM FooHistory").ShouldBe(0); @@ -644,21 +666,23 @@ public async Task ShouldDeleteTemporalTablesData() [Fact] public async Task ShouldResetTemporalTableDefaultName() { - _database.Execute("drop table if exists FooHistory"); - _database.Execute("IF OBJECT_ID(N'Foo', N'U') IS NOT NULL alter table Foo set (SYSTEM_VERSIONING = OFF)"); - _database.Execute("drop table if exists Foo"); + await _database.ExecuteAsync("drop table if exists FooHistory"); + await _database.ExecuteAsync("IF OBJECT_ID(N'Foo', N'U') IS NOT NULL alter table Foo set (SYSTEM_VERSIONING = OFF)"); + await _database.ExecuteAsync("drop table if exists Foo"); - _database.Execute("create table Foo (Value [int] not null primary key clustered, " + - "ValidFrom datetime2 generated always as row start, " + - "ValidTo datetime2 generated always as row end," + - " period for system_time(ValidFrom, ValidTo)" + - ") with (system_versioning = on (history_table = dbo.FooHistory))"); + await _database.ExecuteAsync("create table Foo (Value [int] not null primary key clustered, " + + "ValidFrom datetime2 generated always as row start, " + + "ValidTo datetime2 generated always as row end," + + " period for system_time(ValidFrom, ValidTo)" + + ") with (system_versioning = on (history_table = dbo.FooHistory))"); - _database.Execute("INSERT Foo (Value) VALUES (1)"); - _database.Execute("UPDATE Foo SET Value = 2 Where Value = 1"); + await _database.ExecuteAsync("INSERT Foo (Value) VALUES (1)"); + await _database.ExecuteAsync("UPDATE Foo SET Value = 2 Where Value = 1"); - var checkpoint = new Checkpoint(); - checkpoint.CheckTemporalTables = true; + var checkpoint = new Checkpoint + { + CheckTemporalTables = true + }; await checkpoint.Reset(_connection); var sql = @" @@ -673,20 +697,22 @@ FROM sys.tables t1 public async Task ShouldResetTemporalTableAnonymousName() { // _database.Execute("drop table if exists FooHistory"); - _database.Execute("IF OBJECT_ID(N'Foo', N'U') IS NOT NULL alter table Foo set (SYSTEM_VERSIONING = OFF)"); - _database.Execute("drop table if exists Foo"); + await _database.ExecuteAsync("IF OBJECT_ID(N'Foo', N'U') IS NOT NULL alter table Foo set (SYSTEM_VERSIONING = OFF)"); + await _database.ExecuteAsync("drop table if exists Foo"); - _database.Execute("create table Foo (Value [int] not null primary key clustered, " + - "ValidFrom datetime2 generated always as row start, " + - "ValidTo datetime2 generated always as row end," + - " period for system_time(ValidFrom, ValidTo)" + - ") with (system_versioning = on)"); + await _database.ExecuteAsync("create table Foo (Value [int] not null primary key clustered, " + + "ValidFrom datetime2 generated always as row start, " + + "ValidTo datetime2 generated always as row end," + + " period for system_time(ValidFrom, ValidTo)" + + ") with (system_versioning = on)"); - _database.Execute("INSERT Foo (Value) VALUES (1)"); - _database.Execute("UPDATE Foo SET Value = 2 Where Value = 1"); + await _database.ExecuteAsync("INSERT Foo (Value) VALUES (1)"); + await _database.ExecuteAsync("UPDATE Foo SET Value = 2 Where Value = 1"); - var checkpoint = new Checkpoint(); - checkpoint.CheckTemporalTables = true; + var checkpoint = new Checkpoint + { + CheckTemporalTables = true + }; await checkpoint.Reset(_connection); var sql = @" @@ -700,20 +726,22 @@ FROM sys.tables t1 [Fact] public async Task ShouldDeleteTemporalTablesDataFromNotDefaultSchemas() { - _database.Execute("CREATE SCHEMA [TableSchema] AUTHORIZATION [dbo];"); - _database.Execute("CREATE SCHEMA [HistorySchema] AUTHORIZATION [dbo];"); + await _database.ExecuteAsync("CREATE SCHEMA [TableSchema] AUTHORIZATION [dbo];"); + await _database.ExecuteAsync("CREATE SCHEMA [HistorySchema] AUTHORIZATION [dbo];"); - _database.Execute("create table TableSchema.Foo (Value [int] not null primary key clustered, " + - "ValidFrom datetime2 generated always as row start, " + - "ValidTo datetime2 generated always as row end," + - " period for system_time(ValidFrom, ValidTo)" + - ") with (system_versioning = on (history_table = HistorySchema.FooHistory))"); + await _database.ExecuteAsync("create table TableSchema.Foo (Value [int] not null primary key clustered, " + + "ValidFrom datetime2 generated always as row start, " + + "ValidTo datetime2 generated always as row end," + + " period for system_time(ValidFrom, ValidTo)" + + ") with (system_versioning = on (history_table = HistorySchema.FooHistory))"); - _database.Execute("INSERT TableSchema.Foo (Value) VALUES (1)"); - _database.Execute("UPDATE TableSchema.Foo SET Value = 2 Where Value = 1"); + await _database.ExecuteAsync("INSERT TableSchema.Foo (Value) VALUES (1)"); + await _database.ExecuteAsync("UPDATE TableSchema.Foo SET Value = 2 Where Value = 1"); - var checkpoint = new Checkpoint(); - checkpoint.CheckTemporalTables = true; + var checkpoint = new Checkpoint + { + CheckTemporalTables = true + }; await checkpoint.Reset(_connection); _database.ExecuteScalar("SELECT COUNT(1) FROM HistorySchema.FooHistory").ShouldBe(0); diff --git a/Respawn.UnitTests/Respawn.UnitTests.csproj b/Respawn.UnitTests/Respawn.UnitTests.csproj index 9707530..e68696d 100644 --- a/Respawn.UnitTests/Respawn.UnitTests.csproj +++ b/Respawn.UnitTests/Respawn.UnitTests.csproj @@ -1,17 +1,14 @@  - net461;netcoreapp3.1 + net6.0 - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/Respawn.sln b/Respawn.sln index 4edcae0..a5e1025 100644 --- a/Respawn.sln +++ b/Respawn.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30204.135 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32002.185 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Respawn", "Respawn\Respawn.csproj", "{A326B923-6CAB-48C7-82C7-8BB6780E2479}" EndProject @@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .gitignore = .gitignore Build.ps1 = Build.ps1 .github\workflows\ci.yml = .github\workflows\ci.yml + Directory.Build.props = Directory.Build.props docker-compose.yml = docker-compose.yml Push.ps1 = Push.ps1 .github\workflows\release.yml = .github\workflows\release.yml diff --git a/Respawn/Checkpoint.cs b/Respawn/Checkpoint.cs index dc02eec..51c85ce 100644 --- a/Respawn/Checkpoint.cs +++ b/Respawn/Checkpoint.cs @@ -10,25 +10,23 @@ namespace Respawn { public class Checkpoint { - private GraphBuilder _graphBuilder; private IList _temporalTables = new List(); - public string[] TablesToIgnore { get; set; } = new string[0]; - public string[] TablesToInclude { get; set; } = new string[0]; - public string[] SchemasToInclude { get; set; } = new string[0]; - public string[] SchemasToExclude { get; set; } = new string[0]; - public string DeleteSql { get; private set; } - public string ReseedSql { get; private set; } - public bool CheckTemporalTables { get; set; } = false; - internal string DatabaseName { get; private set; } - public bool WithReseed { get; set; } = false; - public IDbAdapter DbAdapter { get; set; } = Respawn.DbAdapter.SqlServer; + public string[] TablesToIgnore { get; init; } = Array.Empty(); + public string[] TablesToInclude { get; init; } = Array.Empty(); + public string[] SchemasToInclude { get; init; } = Array.Empty(); + public string[] SchemasToExclude { get; init; } = Array.Empty(); + public string? DeleteSql { get; private set; } + public string? ReseedSql { get; private set; } + public bool CheckTemporalTables { get; init; } + public bool WithReseed { get; init; } + public IDbAdapter DbAdapter { get; init; } = Respawn.DbAdapter.SqlServer; - public int? CommandTimeout { get; set; } + public int? CommandTimeout { get; init; } public virtual async Task Reset(string nameOrConnectionString) { - using var connection = new SqlConnection(nameOrConnectionString); + await using var connection = new SqlConnection(nameOrConnectionString); await connection.OpenAsync(); @@ -39,7 +37,6 @@ public virtual async Task Reset(DbConnection connection) { if (string.IsNullOrWhiteSpace(DeleteSql)) { - DatabaseName = connection.Database; await BuildDeleteTables(connection); } @@ -60,8 +57,8 @@ public virtual async Task Reset(DbConnection connection) private async Task ExecuteAlterSystemVersioningAsync(DbConnection connection, string commandText) { - using var tx = connection.BeginTransaction(); - using var cmd = connection.CreateCommand(); + await using var tx = await connection.BeginTransactionAsync(); + await using var cmd = connection.CreateCommand(); cmd.CommandTimeout = CommandTimeout ?? cmd.CommandTimeout; cmd.CommandText = commandText; @@ -69,13 +66,13 @@ private async Task ExecuteAlterSystemVersioningAsync(DbConnection connection, st await cmd.ExecuteNonQueryAsync(); - tx.Commit(); + await tx.CommitAsync(); } private async Task ExecuteDeleteSqlAsync(DbConnection connection) { - using var tx = connection.BeginTransaction(); - using var cmd = connection.CreateCommand(); + await using var tx = await connection.BeginTransactionAsync(); + await using var cmd = connection.CreateCommand(); cmd.CommandTimeout = CommandTimeout ?? cmd.CommandTimeout; cmd.CommandText = DeleteSql; @@ -89,7 +86,7 @@ private async Task ExecuteDeleteSqlAsync(DbConnection connection) await cmd.ExecuteNonQueryAsync(); } - tx.Commit(); + await tx.CommitAsync(); } private async Task BuildDeleteTables(DbConnection connection) @@ -103,32 +100,32 @@ private async Task BuildDeleteTables(DbConnection connection) var allRelationships = await GetRelationships(connection); - _graphBuilder = new GraphBuilder(allTables, allRelationships); + var graphBuilder = new GraphBuilder(allTables, allRelationships); - DeleteSql = DbAdapter.BuildDeleteCommandText(_graphBuilder); - ReseedSql = WithReseed ? DbAdapter.BuildReseedSql(_graphBuilder.ToDelete) : null; + DeleteSql = DbAdapter.BuildDeleteCommandText(graphBuilder); + ReseedSql = WithReseed ? DbAdapter.BuildReseedSql(graphBuilder.ToDelete) : null; } private async Task> GetRelationships(DbConnection connection) { - var rels = new HashSet(); + var relationships = new HashSet(); var commandText = DbAdapter.BuildRelationshipCommandText(this); - using var cmd = connection.CreateCommand(); + await using var cmd = connection.CreateCommand(); cmd.CommandText = commandText; - - using var reader = await cmd.ExecuteReaderAsync(); + + await using var reader = await cmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { - rels.Add(new Relationship( + relationships.Add(new Relationship( new Table(await reader.IsDBNullAsync(0) ? null : reader.GetString(0), reader.GetString(1)), new Table(await reader.IsDBNullAsync(2) ? null : reader.GetString(2), reader.GetString(3)), reader.GetString(4))); } - return rels; + return relationships; } private async Task> GetAllTables(DbConnection connection) @@ -137,11 +134,11 @@ private async Task> GetAllTables(DbConnection connection) var commandText = DbAdapter.BuildTableCommandText(this); - using var cmd = connection.CreateCommand(); + await using var cmd = connection.CreateCommand(); cmd.CommandText = commandText; - using var reader = await cmd.ExecuteReaderAsync(); + await using var reader = await cmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { @@ -157,11 +154,11 @@ private async Task> GetAllTemporalTables(DbConnection conne var commandText = DbAdapter.BuildTemporalTableCommandText(this); - using var cmd = connection.CreateCommand(); + await using var cmd = connection.CreateCommand(); cmd.CommandText = commandText; - using var reader = await cmd.ExecuteReaderAsync(); + await using var reader = await cmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { diff --git a/Respawn/Graph/Table.cs b/Respawn/Graph/Table.cs index b2f37d0..8162c5b 100644 --- a/Respawn/Graph/Table.cs +++ b/Respawn/Graph/Table.cs @@ -3,15 +3,15 @@ namespace Respawn.Graph { - public class Table + public class Table : IEquatable { - public Table(string schema, string name) + public Table(string? schema, string name) { Schema = schema; Name = name; } - public string Schema { get; } + public string? Schema { get; } public string Name { get; } public HashSet Relationships { get; } = new(); @@ -21,32 +21,35 @@ public string GetFullName(char quoteIdentifier) => ? $"{quoteIdentifier}{Name}{quoteIdentifier}" : $"{quoteIdentifier}{Schema}{quoteIdentifier}.{quoteIdentifier}{Name}{quoteIdentifier}"; - public bool Equals(Table other) + public bool Equals(Table? other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; - return string.Equals(Name, other.Name) && string.Equals(Schema, other.Schema); + return Schema == other.Schema && Name == other.Name; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (obj.GetType() != GetType()) return false; return Equals((Table) obj); } public override int GetHashCode() { - unchecked - { - return ((Name != null ? Name.GetHashCode() : 0) * 397) ^ (Schema != null ? Schema.GetHashCode() : 0); - } + return HashCode.Combine(Schema, Name); } - public static bool operator ==(Table left, Table right) => Equals(left, right); + public static bool operator ==(Table? left, Table? right) + { + return Equals(left, right); + } - public static bool operator !=(Table left, Table right) => !Equals(left, right); + public static bool operator !=(Table? left, Table? right) + { + return !Equals(left, right); + } public override string ToString() => $"{Schema}.{Name}"; } diff --git a/Respawn/Graph/TemporalTable.cs b/Respawn/Graph/TemporalTable.cs index 8053061..a921c2a 100644 --- a/Respawn/Graph/TemporalTable.cs +++ b/Respawn/Graph/TemporalTable.cs @@ -1,4 +1,4 @@ namespace Respawn.Graph { - public record TemporalTable(string Schema, string Name, string HistoryTableSchema, string HistoryTableName); + public record TemporalTable(string? Schema, string Name, string? HistoryTableSchema, string HistoryTableName); } diff --git a/Respawn/MySqlAdapter.cs b/Respawn/MySqlAdapter.cs index ea55940..926e557 100644 --- a/Respawn/MySqlAdapter.cs +++ b/Respawn/MySqlAdapter.cs @@ -19,25 +19,25 @@ information_schema.tables AS t table_type = 'BASE TABLE' AND TABLE_SCHEMA NOT IN ('mysql' , 'performance_schema')"; - if (checkpoint.TablesToIgnore != null && checkpoint.TablesToIgnore.Any()) + if (checkpoint.TablesToIgnore.Any()) { var args = string.Join(",", checkpoint.TablesToIgnore.Select(t => $"'{t}'")); commandText += " AND t.TABLE_NAME NOT IN (" + args + ")"; } - if (checkpoint.TablesToInclude != null && checkpoint.TablesToInclude.Any()) + if (checkpoint.TablesToInclude.Any()) { var args = string.Join(",", checkpoint.TablesToInclude.Select(t => $"'{t}'")); commandText += " AND t.TABLE_NAME IN (" + args + ")"; } - if (checkpoint.SchemasToExclude != null && checkpoint.SchemasToExclude.Any()) + if (checkpoint.SchemasToExclude.Any()) { var args = string.Join(",", checkpoint.SchemasToExclude.Select(t => $"'{t}'")); commandText += " AND t.TABLE_SCHEMA NOT IN (" + args + ")"; } - else if (checkpoint.SchemasToInclude != null && checkpoint.SchemasToInclude.Any()) + else if (checkpoint.SchemasToInclude.Any()) { var args = string.Join(",", checkpoint.SchemasToInclude.Select(t => $"'{t}'")); @@ -60,22 +60,22 @@ public string BuildRelationshipCommandText(Checkpoint checkpoint) var whereText = new List(); - if (checkpoint.TablesToIgnore != null && checkpoint.TablesToIgnore.Any()) + if (checkpoint.TablesToIgnore.Any()) { var args = string.Join(",", checkpoint.TablesToIgnore.Select(t => $"'{t}'")); whereText.Add("TABLE_NAME NOT IN (" + args + ")"); } - if (checkpoint.TablesToInclude != null && checkpoint.TablesToInclude.Any()) + if (checkpoint.TablesToInclude.Any()) { var args = string.Join(",", checkpoint.TablesToInclude.Select(t => $"'{t}'")); whereText.Add("TABLE_NAME IN (" + args + ")"); } - if (checkpoint.SchemasToExclude != null && checkpoint.SchemasToExclude.Any()) + if (checkpoint.SchemasToExclude.Any()) { var args = string.Join(",", checkpoint.SchemasToExclude.Select(t => $"'{t}'")); whereText.Add("CONSTRAINT_SCHEMA NOT IN (" + args + ")"); } - else if (checkpoint.SchemasToInclude != null && checkpoint.SchemasToInclude.Any()) + else if (checkpoint.SchemasToInclude.Any()) { var args = string.Join(",", checkpoint.SchemasToInclude.Select(t => $"'{t}'")); whereText.Add("CONSTRAINT_SCHEMA IN (" + args + ")"); diff --git a/Respawn/OracleDbAdapter.cs b/Respawn/OracleDbAdapter.cs index 1ff384f..e920527 100644 --- a/Respawn/OracleDbAdapter.cs +++ b/Respawn/OracleDbAdapter.cs @@ -86,7 +86,7 @@ public string BuildDeleteCommandText(GraphBuilder graph) return $"BEGIN\n{deleteSql}\nEND;"; } - private IEnumerable BuildCommands(GraphBuilder graph) + private static IEnumerable BuildCommands(GraphBuilder graph) { foreach (var rel in graph.CyclicalTableRelationships) { diff --git a/Respawn/Respawn.csproj b/Respawn/Respawn.csproj index 12d548c..f92c59e 100644 --- a/Respawn/Respawn.csproj +++ b/Respawn/Respawn.csproj @@ -4,7 +4,7 @@ Intelligent checkpoints for database tests Copyright Jimmy Bogard Jimmy Bogard - net461;netstandard2.0 + netstandard2.1 Respawn Respawn tests;integration tests;database tests @@ -17,6 +17,7 @@ true true true + enable @@ -24,15 +25,9 @@ - - - - + + + - - - - - diff --git a/Respawn/SqlServerDbAdapter.cs b/Respawn/SqlServerDbAdapter.cs index 1b6e730..82d116a 100644 --- a/Respawn/SqlServerDbAdapter.cs +++ b/Respawn/SqlServerDbAdapter.cs @@ -60,25 +60,25 @@ sys.foreign_keys sfk inner join sys.schemas fk_schema on so_fk.schema_id = fk_schema.schema_id where 1=1"; - if (checkpoint.TablesToIgnore != null && checkpoint.TablesToIgnore.Any()) + if (checkpoint.TablesToIgnore.Any()) { var args = string.Join(",", checkpoint.TablesToIgnore.Select(t => $"N'{t}'")); commandText += " AND so_pk.name NOT IN (" + args + ")"; } - if (checkpoint.TablesToInclude != null && checkpoint.TablesToInclude.Any()) + if (checkpoint.TablesToInclude.Any()) { var args = string.Join(",", checkpoint.TablesToInclude.Select(t => $"N'{t}'")); commandText += " AND so_pk.name IN (" + args + ")"; } - if (checkpoint.SchemasToExclude != null && checkpoint.SchemasToExclude.Any()) + if (checkpoint.SchemasToExclude.Any()) { var args = string.Join(",", checkpoint.SchemasToExclude.Select(t => $"N'{t}'")); commandText += " AND pk_schema.name NOT IN (" + args + ")"; } - else if (checkpoint.SchemasToInclude != null && checkpoint.SchemasToInclude.Any()) + else if (checkpoint.SchemasToInclude.Any()) { var args = string.Join(",", checkpoint.SchemasToInclude.Select(t => $"N'{t}'"));