Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling of multiple go statements #21

Merged
merged 2 commits into from
Jul 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 61 additions & 1 deletion DataDude.Tests/Inserts/AutoInsertFKTableTestscs.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DataDude.Instructions.Insert;
using DataDude.Instructions.Insert.AutomaticForeignKeys;
Expand Down Expand Up @@ -113,5 +114,64 @@ public async Task Handles_Ignore_Nullable_Keys()
.Select(x => x.TableName)
.ShouldBe(new[] { "B" });
}

[Fact]
public async Task Handles_Previously_Inserted_Rows()
{
var schema = new TestSchema();
var a = schema.AddTable("A");
var b = schema.AddTable("B").AddFk(a);
var c = schema.AddTable("C").AddFk(b);

var context = new DataDudeContext(schema);
await context.LoadSchema(null, null);

// Simulate that dude.Go(..) from a previous execution has been executed and a row has already been inserted into table A
InsertContext.Get(context).InsertedRows.Add(new InsertedRow(a, new Dictionary<string, object>(), null));

context.Instructions.Add(new InsertInstruction("C"));
var dependencyService = new DependencyService(DependencyTraversalStrategy.FollowAllForeignKeys);
await new AddMissingInsertInstructionsPreProcessor(dependencyService).PreProcess(context);
context.Instructions
.OfType<InsertInstruction>()
.Select(x => x.TableName)
.ShouldBe(new[] { "[dbo].[B]", "C" });
}

[Fact]
public void Can_Enable_AutoFks_Multiple_Times()
{
var dude = new Dude()
.EnableAutomaticForeignKeys(x => x.AddMissingForeignKeys = false)
.EnableAutomaticForeignKeys(x => x.AddMissingForeignKeys = true);

dude.Configure(context =>
{
context.InstructionPreProcessors.OfType<AddMissingInsertInstructionsPreProcessor>().ShouldHaveSingleItem();
});

dude.ConfigureInsert(insertContext =>
{
insertContext.InsertInterceptors.OfType<ForeignKeyInterceptor>().ShouldHaveSingleItem();
});
}

[Fact]
public void Can_Disable_AutoFks()
{
var dude = new Dude()
.EnableAutomaticForeignKeys(x => x.AddMissingForeignKeys = true)
.DisableAutomaticForeignKeys();

dude.Configure(context =>
{
context.InstructionPreProcessors.OfType<AddMissingInsertInstructionsPreProcessor>().ShouldBeEmpty();
});

dude.ConfigureInsert(insertContext =>
{
insertContext.InsertInterceptors.OfType<ForeignKeyInterceptor>().ShouldBeEmpty();
});
}
}
}
33 changes: 33 additions & 0 deletions DataDude.Tests/Inserts/InstructionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ public async Task Can_Insert_With_Automatic_Foreign_Keys_And_Add_Missing_Insert_
.Insert("OfficeOccupant")
.Go(connection);

var offices = await connection.QueryAsync<dynamic>("SELECT * FROM Buildings.Office");
offices.ShouldHaveSingleItem();

var employees = await connection.QueryAsync<dynamic>("SELECT * FROM People.Employee");
offices.ShouldHaveSingleItem();

var occupants = await connection.QueryAsync<dynamic>("SELECT * FROM Buildings.OfficeOccupant");
occupants.ShouldHaveSingleItem();
}
Expand Down Expand Up @@ -312,5 +318,32 @@ await dude
insertedOffices.ShouldBe(1);
insertedEmployees.ShouldBe(1);
}

[Fact]
public async Task Split_Inserts_Keeps_Track_Of_Previously_Inserted_Data()
{
using var connection = Fixture.CreateNewConnection();

var dude = new Dude()
.EnableAutomaticForeignKeys(x => x.AddMissingForeignKeys = true);

// Inserts Office, Employee, OfficeOccupant and OfficeOccupancy
await dude.Insert("OfficeOccupancy").Go(connection);

// Should insert OfficeOccupancy only
await dude.Insert("OfficeOccupancy").Go(connection);

var offices = await connection.QueryAsync<dynamic>("SELECT * FROM Buildings.Office");
offices.ShouldHaveSingleItem();

var employees = await connection.QueryAsync<dynamic>("SELECT * FROM People.Employee");
offices.ShouldHaveSingleItem();

var occupants = await connection.QueryAsync<dynamic>("SELECT * FROM Buildings.OfficeOccupant");
occupants.ShouldHaveSingleItem();

var officeOccupancies = await connection.QueryAsync<dynamic>("SELECT * FROM People.OfficeOccupancy");
officeOccupancies.ShouldContain(x => true, 2, "Should contain two occupancies");
}
}
}
2 changes: 1 addition & 1 deletion DataDude/DataDude.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>9.0</LangVersion>
<Nullable>enable</Nullable>
<Version>0.7.0</Version>
<Version>0.7.1</Version>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ public Task PreProcess(DataDudeContext context)
{
if (context.Schema?[instruction.TableName] is { } table)
{
IEnumerable<InsertedRow> insertedRows = InsertContext.Get(context)?.InsertedRows ?? Array.Empty<InsertedRow>();
var dependencies = _dependencyService.GetOrderedDependenciesFor(table)
.Where(t => !toInsert.Values.Any(x => x.Contains(t)))
.Where(t => !insertedRows.Any(x => x.Table == t))
.ToList();

toInsert.Add(instruction, new InsertInformation(table, dependencies));
Expand Down
32 changes: 31 additions & 1 deletion DataDude/Instructions/Insert/InsertExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@ public static Dude EnableAutomaticForeignKeys(this Dude dude, Action<AutoFKConfi
var config = new AutoFKConfiguration();
configure?.Invoke(config);

DisableAutomaticForeignKeys(dude);

// Insert first in order to run before identity insert interceptor
dude.ConfigureInsert(x => x.InsertInterceptors.Insert(0, new ForeignKeyInterceptor()));
dude.ConfigureInsert(insertContext =>
{
insertContext.InsertInterceptors.Insert(0, new ForeignKeyInterceptor());
});

if (config.AddMissingForeignKeys)
{
Expand All @@ -43,6 +48,31 @@ public static Dude EnableAutomaticForeignKeys(this Dude dude, Action<AutoFKConfi
return dude;
}

public static Dude DisableAutomaticForeignKeys(this Dude dude)
{
// Clean out existing ForeignKeyInterceptor
dude.ConfigureInsert(insertContext =>
{
var existingInterceptors = insertContext.InsertInterceptors.OfType<ForeignKeyInterceptor>().ToList();
foreach (var existingFKInterceptors in existingInterceptors)
{
insertContext.InsertInterceptors.Remove(existingFKInterceptors);
}
});

// Clean out existing AddMissingInsertInstructionsPreProcessors
dude.Configure(x =>
{
var existingPreProcessors = x.InstructionPreProcessors.OfType<AddMissingInsertInstructionsPreProcessor>().ToList();
foreach (var existingPreProcessor in existingPreProcessors)
{
x.InstructionPreProcessors.Remove(existingPreProcessor);
}
});

return dude;
}

public static Dude ConfigureCustomColumnValue(this Dude dude, Action<ColumnInformation, ColumnValue> getValue)
{
dude.ConfigureInsert(x => x.InsertValueProviders.Insert(0, new CustomValueProvider(getValue)));
Expand Down