Skip to content

Commit

Permalink
Fix MigrationArgsBase.Assemblies handling. (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
chullybun committed Mar 29, 2023
1 parent 91cab4f commit ea01cc5
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 18 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

Represents the **NuGet** versions.

## v2.3.4
- *Fixed:* `MigrationArgsBase.Assemblies` internal list management simplified; all order/sequencing managed within `DatabaseMigrationBase` implementation to limit issues. Added a new `AddAssemblyAfter` to support explicit positioning where needed.

## v2.3.3
- *Fixed:* The unquoting of identifiers whilst parsing schema objects resulted in an empty identifier where the quote was not specified; i.e. for SQL Server `[dbo].[name]` worked, whereas, `dbo.name` did not; this has been corrected.

Expand Down
2 changes: 1 addition & 1 deletion Common.targets
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>2.3.3</Version>
<Version>2.3.4</Version>
<LangVersion>preview</LangVersion>
<Authors>Avanade</Authors>
<Company>Avanade</Company>
Expand Down
3 changes: 3 additions & 0 deletions src/DbEx.MySql/Migration/MySqlMigration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ public MySqlMigration(MigrationArgsBase args) : base(args)
csb.Database = null;
_masterDatabase = new MySqlDatabase(() => new MySqlConnection(csb.ConnectionString));

// Add this assembly for probing.
Args.AddAssemblyAfter(typeof(DatabaseMigrationBase).Assembly, typeof(MySqlMigration).Assembly);

// Defaults the schema object types unless already specified.
if (SchemaObjectTypes.Length == 0)
SchemaObjectTypes = new string[] { "FUNCTION", "VIEW", "PROCEDURE" };
Expand Down
4 changes: 3 additions & 1 deletion src/DbEx.SqlServer/Migration/SqlServerMigration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using DbUp.Support;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Logging;
using OnRamp.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -46,6 +45,9 @@ public SqlServerMigration(MigrationArgsBase args) : base(args)
csb.InitialCatalog = "master";
_masterDatabase = new SqlServerDatabase(() => new SqlConnection(csb.ConnectionString));

// Add this assembly for probing.
Args.AddAssemblyAfter(typeof(DatabaseMigrationBase).Assembly, typeof(SqlServerMigration).Assembly);

// Where no data reset predicate filter added then default to exclude 'dbo' and 'cdc'; where a dev needs to do all then they can override with following predicate: schema => true;
if (Args.DataResetFilterPredicate == null)
Args.DataResetFilterPredicate = schema => schema.Schema != "dbo" || schema.Schema != "cdc";
Expand Down
12 changes: 6 additions & 6 deletions src/DbEx/Migration/DatabaseMigrationBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ protected DatabaseMigrationBase(MigrationArgsBase args)
public ILogger Logger => Args.Logger!;

/// <summary>
/// Gets the root namespaces for the <see cref="MigrationArgsBase.Assemblies"/>.
/// Gets the root namespaces for the <see cref="MigrationArgsBase.Assemblies"/> (ordered by <see cref="MigrationArgsBase.ProbeAssemblies"/>).
/// </summary>
protected IEnumerable<string> Namespaces { get; } = new List<string>();

Expand Down Expand Up @@ -235,7 +235,7 @@ private void PreExecutionInitialization()
_hasInitialized = true;

var list = (List<string>)Namespaces;
Args.Assemblies.ForEach(x => list.Add(x.GetName().Name));
Args.ProbeAssemblies.ForEach(x => list.Add(x.GetName().Name));

// Walk the assembly hierarchy.
var alist = new List<Assembly>();
Expand Down Expand Up @@ -439,7 +439,7 @@ protected virtual async Task<bool> DatabaseCreateAsync(CancellationToken cancell
Logger.LogInformation("{Content}", $" Probing for '{OnDatabaseCreateName}' embedded resources: {string.Join(", ", GetNamespacesWithSuffix($"{MigrationsNamespace}.*.sql"))}");

var scripts = new List<DatabaseMigrationScript>();
foreach (var ass in Args.Assemblies)
foreach (var ass in Args.ProbeAssemblies)
{
foreach (var name in ass.GetManifestResourceNames().Where(rn => Namespaces.Any(ns => rn.StartsWith($"{ns}.{MigrationsNamespace}.", StringComparison.InvariantCulture) && rn.EndsWith($".{OnDatabaseCreateName}.sql", StringComparison.InvariantCultureIgnoreCase))).OrderBy(x => x))
{
Expand All @@ -465,7 +465,7 @@ private async Task<bool> DatabaseMigrateAsync(CancellationToken cancellationToke
Logger.LogInformation("{Content}", $" Probing for embedded resources: {string.Join(", ", GetNamespacesWithSuffix($"{MigrationsNamespace}.*.sql"))}");

var scripts = new List<DatabaseMigrationScript>();
foreach (var ass in Args.Assemblies)
foreach (var ass in Args.ProbeAssemblies)
{
foreach (var name in ass.GetManifestResourceNames().Where(rn => Namespaces.Any(ns => rn.StartsWith($"{ns}.{MigrationsNamespace}.", StringComparison.InvariantCulture))).OrderBy(x => x))
{
Expand Down Expand Up @@ -532,7 +532,7 @@ private async Task<bool> DatabaseSchemaAsync(CancellationToken cancellationToken

// Get all the resources from the assemblies.
Logger.LogInformation("{Content}", $" Probing for embedded resources: {string.Join(", ", GetNamespacesWithSuffix($"{SchemaNamespace}.*.sql"))}");
foreach (var ass in Args.Assemblies)
foreach (var ass in Args.ProbeAssemblies)
{
foreach (var rn in ass.GetManifestResourceNames().OrderBy(x => x))
{
Expand Down Expand Up @@ -698,7 +698,7 @@ private async Task<bool> DatabaseDataAsync(CancellationToken cancellationToken)
Logger.LogInformation("{Content}", $" Probing for embedded resources: {string.Join(", ", GetNamespacesWithSuffix($"{DataNamespace}.*.[sql|yaml]", true))}");

var list = new List<(Assembly Assembly, string ResourceName)>();
foreach (var ass in Args.Assemblies.Reverse<Assembly>()) // Reversed as assumed data builds on top of earlier.
foreach (var ass in Args.Assemblies.Distinct()) // Assumed data builds on top of earlier (do not use ProbeAssemblies as this is reversed).
{
foreach (var rn in ass.GetManifestResourceNames().OrderBy(x => x))
{
Expand Down
43 changes: 37 additions & 6 deletions src/DbEx/Migration/MigrationArgsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,15 @@ public abstract class MigrationArgsBase : OnRamp.CodeGeneratorDbArgsBase
public MigrationCommand MigrationCommand { get; set; } = MigrationCommand.None;

/// <summary>
/// Gets the <see cref="Assembly"/> list to use to probe for assembly resource (in defined sequence); will check this assembly also (no need to explicitly specify).
/// Gets the <see cref="Assembly"/> list to use to probe for assembly resource (in defined sequence); will automatically add this (DbEx) assembly also (therefore no need to explicitly specify).
/// </summary>
public List<Assembly> Assemblies { get; } = new List<Assembly> { typeof(MigrationArgs).Assembly };

/// <summary>
/// Gets the <see cref="Assemblies"/> reversed in order for probe-based sequencing.
/// </summary>
public IEnumerable<Assembly> ProbeAssemblies => Assemblies.Distinct().Reverse();

/// <summary>
/// Gets the runtime parameters.
/// </summary>
Expand Down Expand Up @@ -98,19 +103,45 @@ public abstract class MigrationArgsBase : OnRamp.CodeGeneratorDbArgsBase
public Func<DbSchema.DbTableSchema, bool>? DataResetFilterPredicate { get; set; }

/// <summary>
/// Adds (inserts) one or more <paramref name="assemblies"/> to <see cref="Assemblies"/> (before any existing values).
/// Adds one or more <paramref name="assemblies"/> to the <see cref="Assemblies"/>.
/// </summary>
/// <param name="assemblies">The assemblies to add.</param>
/// <remarks>The order in which they are specified is the order in which they will be probed for embedded resources.</remarks>
/// <remarks>Where a specified <see cref="Assembly"/> item already exists within the <see cref="Assemblies"/> it will not be added again.</remarks>
public void AddAssembly(params Assembly[] assemblies)
{
foreach (var a in assemblies.Distinct().Reverse())
foreach (var assembly in assemblies)
{
if (!Assemblies.Contains(a))
Assemblies.Insert(0, a);
if (!Assemblies.Contains(assembly))
Assemblies.Add(assembly);
}
}

/// <summary>
/// Adds one or more <paramref name="assemblies"/> to the <see cref="Assemblies"/> after the specified <paramref name="assemblyToFind"/>; where not found, will be added to the end.
/// </summary>
/// <param name="assemblyToFind">The <see cref="Assembly"/> to find within the existing <see cref="Assemblies"/>.</param>
/// <param name="assemblies">The assemblies to add</param>
/// <remarks>Where a specified <see cref="Assembly"/> item already exists within the <see cref="Assemblies"/> it will not be added again.</remarks>
public void AddAssemblyAfter(Assembly assemblyToFind, params Assembly[] assemblies)
{
var index = Assemblies.IndexOf(assemblyToFind ?? throw new ArgumentNullException(nameof(assemblyToFind)));
if (index < 0)
{
AddAssembly(assemblies);
return;
}

var newAssemblies = new List<Assembly>();
foreach (var assembly in assemblies)
{
if (!Assemblies.Contains(assembly))
newAssemblies.Add(assembly);
}


Assemblies.InsertRange(index + 1, newAssemblies);
}

/// <summary>
/// Adds a parameter to the <see cref="MigrationArgsBase.Parameters"/> where it does not already exist; unless <paramref name="overrideExisting"/> is selected then it will add or override.
/// </summary>
Expand Down
7 changes: 3 additions & 4 deletions src/DbEx/Migration/MigrationArgsBaseT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ namespace DbEx.Migration
public abstract class MigrationArgsBase<TSelf> : MigrationArgsBase where TSelf : MigrationArgsBase<TSelf>
{
/// <summary>
/// Adds (inserts) one or more <paramref name="assemblies"/> to <see cref="MigrationArgsBase.Assemblies"/> (before any existing values; i.e. last in first out/probed).
/// Adds one or more <paramref name="assemblies"/> to the <see cref="MigrationArgsBase.Assemblies"/>.
/// </summary>
/// <param name="assemblies">The assemblies to add.</param>
/// <remarks>The order in which they are specified is the order in which they will be probed for embedded resources.</remarks>
/// <returns>The current <see cref="MigrationArgsBase{TSelf}"/> instance to support fluent-style method-chaining.</returns>
public new TSelf AddAssembly(params Assembly[] assemblies)
{
Expand All @@ -25,7 +24,7 @@ public new TSelf AddAssembly(params Assembly[] assemblies)
}

/// <summary>
/// Adds (inserts) one or more <paramref name="types"/> (being the underlying <see cref="Type.Assembly"/>) to <see cref="MigrationArgsBase.Assemblies"/> (before any existing values; i.e. last in first out/probed).
/// Adds one or more <paramref name="types"/> (being the underlying <see cref="Type.Assembly"/>) to <see cref="MigrationArgsBase.Assemblies"/>.
/// </summary>
/// <param name="types">The types to add.</param>
/// <remarks>The order in which they are specified is the order in which they will be probed for embedded resources.</remarks>
Expand All @@ -42,7 +41,7 @@ public TSelf AddAssembly(params Type[] types)
}

/// <summary>
/// Adds (inserts) the <typeparamref name="TAssembly"/> (being the underlying <see cref="Type.Assembly"/>) to <see cref="MigrationArgsBase.Assemblies"/> (before any existing values; i.e. last in first out/probed).
/// Adds the <typeparamref name="TAssembly"/> (being the underlying <see cref="Type.Assembly"/>) to <see cref="MigrationArgsBase.Assemblies"/>.
/// </summary>
public TSelf AddAssembly<TAssembly>() => AddAssembly(typeof(TAssembly));

Expand Down

0 comments on commit ea01cc5

Please sign in to comment.