Fluentmigrator: Embedded script cannot be found in assemblies on .NET Core

Created on 21 May 2018  路  1Comment  路  Source: fluentmigrator/fluentmigrator

I'd like to share an issue which I stumbled upon while migrating to the new version of FluentMigrator on .NET Core. I have a setup in which I store all embedded scripts in a different project, namely Foo.Data and it was working flawlessly till the new version.

It seems even though we configure the runner with .WithMigrationsIn method, it doesn't search those assemblies for the embedded resources, instead, it only searches the assembly which creates the IServiceScope:

using (IServiceScope serviceScope = app.ApplicationServices.CreateScope())
{
    IServiceProvider serviceProvider = serviceScope.ServiceProvider;
    IMigrationRunner migrationRunner = serviceProvider.GetRequiredService<IMigrationRunner>();
    migrationRunner.MigrateUp();
}

To overcome this issue, I had to create an IEmbeddedResourceProvider in my Foo.Data project, which only does the following.

namespace Foo.Data
{
    public class EmbeddedResourceProvider : IEmbeddedResourceProvider
    {
        public IEnumerable<(string name, Assembly assembly)> GetEmbeddedResources()
        {
            Assembly assembly = this.GetType().Assembly;
            foreach (var resourceName in assembly.GetManifestResourceNames())
            {
                yield return (resourceName, assembly);
            }
        }
    }
}

And also I had to replace IEmbeddedResourceProvider definition in service registration:

public static IServiceCollection AddDatabaseMigration(this IServiceCollection services, string connectionString)
{
    return services
        .AddFluentMigratorCore()
        .AddSingleton<IEmbeddedResourceProvider, EmbeddedResourceProvider>()
        .ConfigureRunner(runner =>
            runner
                .AddSqlServer()
                .WithGlobalCommandTimeout(TimeSpan.FromMinutes(5))
                .WithGlobalConnectionString(connectionString)
                .WithMigrationsIn(typeof(DataMigrations).Assembly)
                .WithVersionTable(new VersionTableMetaData())
        );
}

Is there any better solution to this? Wouldn't it be better if it could search the assemblies which are defined in the runner configuration?

improvement

Most helpful comment

There is indeed a difference between IMigrationSource (and IMigrationSourceItem) and IAssemblySource (and IAssemblySourceItem). The former and the latter are for migrations/profiles/stages (everything derived from IMigration) and the latter is also for version table metadata, embedded, resources, etc....

Maybe I should change the WithMigrationsIn to add an IAssemblySourceItem too.

The solution for you would be to remove the WithMigrationsIn call and your custom IEmbeddedResourceProvider and replace them with:

services
    .AddSingleton<IAssemblySourceItem>(() => new AssemblySourceItem(typeof(DataMigrations).Assembly));

>All comments

There is indeed a difference between IMigrationSource (and IMigrationSourceItem) and IAssemblySource (and IAssemblySourceItem). The former and the latter are for migrations/profiles/stages (everything derived from IMigration) and the latter is also for version table metadata, embedded, resources, etc....

Maybe I should change the WithMigrationsIn to add an IAssemblySourceItem too.

The solution for you would be to remove the WithMigrationsIn call and your custom IEmbeddedResourceProvider and replace them with:

services
    .AddSingleton<IAssemblySourceItem>(() => new AssemblySourceItem(typeof(DataMigrations).Assembly));
Was this page helpful?
0 / 5 - 0 ratings

Related issues

tgharold picture tgharold  路  6Comments

ondravondra picture ondravondra  路  8Comments

jayharris picture jayharris  路  6Comments

mabead picture mabead  路  7Comments

n1ghtmare picture n1ghtmare  路  3Comments