fluentmigrator / fluentmigrator

Fluent migrations framework for .NET
https://fluentmigrator.github.io
Apache License 2.0
3.26k stars 656 forks source link

Migrations not found when defined in F# #883

Closed tylerhartwig closed 3 years ago

tylerhartwig commented 6 years ago

Migrations defined in F# fail to be discovered by FluentMigrator when defined in F#.

I have tested this a plethora of ways from F#, each resulting in a different error.

  1. Running using FAKE a) When running without explicitly loading FluentMigrator and FluentMigrator.Abstractions into the load context, these assemblies cannot be found.

    b) When running with these explicitly loaded, a MissingMigrationsException is thrown, even though, to the best of my knowledge, the appropriate class is discoverable.

  2. Running out of process When running using the out of process tool, the tool fails to find FSharp.Core

  3. Running as a separate console application (defined in F#) When running in the separate console application, a SIGSEV is thrown.

I don't think this library explicitly supports F#, and I understand that, however while result 1a seems weird, 1b is really what I'm opening an issue about.

I can reflectively find my Migration's type, and confirm it has the Migration attribute on it. Additionally it implements Migration, so it should be discoverable.

I've run this on the latest core SDK, as well as the latest preview SDK.

I have provided a minimal solution to display the issue.

to run from Fake, the command should be as follows:

  1. .paket/paket.exe install (use mono if not on windows)
  2. dotnet build build.proj

[EDIT]

Fixed problem 1, the migration assembly was being loaded into the wrong context, this is not a FluentMigrator issue.

I will leave this issue open in case 2 and 3 are of interest.

matthid commented 6 years ago

We could at least track down 1): Reason was that fake has it's own load context so the "workaround" was:

type Dummy = Dummy

let migrationAssemblyPath = __SOURCE_DIRECTORY__ + "/Migrations/bin/Release/netstandard2.0/Migrations.dll"
let ctx = AssemblyLoadContext.GetLoadContext(typeof<Dummy>.Assembly)
let migrationAssembly = ctx.LoadFromAssemblyPath(migrationAssemblyPath)

In order to load the assembly into the correct load context (ie the same load context fake loads "FluentMigrator.dll"). There are other workarounds but this is the most "straight forward" one.

tylerhartwig commented 6 years ago

FsFluentMigrator.zip

Updated Solution with workaround

fubar-coder commented 6 years ago

Good that you found a solution. TBH, I'm totally unexperienced when it comes to F#. I'll leave this issue open.

Regarding problem 2: Would it be sufficient when the out-of-process runner would reference FSharp.Core?

I have seen problem 3 when trying to use Microsoft.Data.Sqlite under Linux (sometimes, not always). What is your test platform/version?

matthid commented 6 years ago

Regarding 1): It is not specific to F#, you can definitely have the same problem with for example "cake build" or "c# interactive" depending on how they load their dependencies.

Regarding 2): I would assume that's the general problem of the console runner that it doesn't support additonal dependencies, is that correct?

Would it be sufficient when the out-of-process runner would reference FSharp.Core?

Yes I guess it would be as long as that one is "newer" than the one from the migration library. In fact I would assume the problem "comes back" once the user introduces the next dependency...

fubar-coder commented 6 years ago

Yes, you're correct about 1) and 2). The only solution for 2) would be a deep-dive into the build runner (msbuild, cake, fake, etc...) and determine all references (and reference sources) and somehow trying to load them, which could be difficult due to the fact that app domains aren't supported anymore.

matthid commented 6 years ago

Actually as 2) is about the out of process runner. I guess it either needs some arguments --include-path to tell it to search for dependencies or just assume they live alongside the dll (Which it might already do, I think we didn't try to put FSharp.Core alongside the dll. Putting it alongside the runner might work but is a but unpractical.

fubar-coder commented 6 years ago

The idea behind my comment was, that it would be a huge task to make the out-of-process runner work with the csproj/fsproj as source, because it contains all references (and reference sources) of the migration assembly. Maybe I should take a look how the EF core people do this kind of thing.

My suggestion was/is that the out-of-process runner only makes sense on a dotnet published project, because that ensures that all necessary assemblies are available in the same directory.

tylerhartwig commented 6 years ago

@fubar-coder As for the test platform and version for problem 3.

I am using .NET Core, just a console application, latest version of FluentMigrator (3.0.0).

The database is Postgresql (Npgsql 3.2.7) running on OS X (High Sierra)

I believe those versions are correct, I'm doing this from memory at the moment since I am not home.

nojaf commented 6 years ago

Any updates on this? I'm having similar problems here. I download the tool and place the dotnet-fm.exe next to all my dlls. But when I run it I get

Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.FileLoadException: Could not l
oad file or assembly 'FSharp.Core, Version=4.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. Could not find or load a specific file. (Exception from HRESULT: 0
x80131621) ---> System.IO.FileLoadException: Could not load file or assembly 'FSharp.Core, Version=4.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
   at System.Runtime.Loader.AssemblyLoadContext.LoadFromPath(IntPtr ptrNativeAssemblyLoadContext, String ilPath, String niPath, ObjectHandleOnStack retAssembly)
   at System.Runtime.Loader.AssemblyLoadContext.LoadFromAssemblyPath(String assemblyPath)
   at System.Reflection.Assembly.LoadFrom(String assemblyFile)
   at System.Reflection.Assembly.LoadFromResolveHandler(Object sender, ResolveEventArgs args)
   at System.AppDomain.InvokeResolveEvent(ResolveEventHandler eventHandler, RuntimeAssembly assembly, String name)
   --- End of inner exception stack trace ---
   at System.ModuleHandle.ResolveType(RuntimeModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, Ob
jectHandleOnStack type)
   at System.ModuleHandle.ResolveTypeHandleInternal(RuntimeModule module, Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstan
tiationContext)
   at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
   at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(CustomAttributeRecord caRecord, MetadataImport scope, Assembly& lastAptcaOkAssembly, RuntimeModule de
coratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, Object[] attributes, IList derivedAttributes, RuntimeType& attri
buteType, IRuntimeMethodInfo& ctor, Boolean& ctorHasParameters, Boolean& isVarArg)
   at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType,
 Boolean mustBeInheritable, IList derivedAttributes)
   at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeType type, RuntimeType caType, Boolean inherit)
   at System.Attribute.GetCustomAttributes(MemberInfo element, Type type, Boolean inherit)
   at System.Reflection.CustomAttributeExtensions.GetCustomAttributes[T](MemberInfo element)
   at FluentMigrator.Runner.Infrastructure.DefaultMigrationRunnerConventions.TypeIsProfileImpl(Type type) in /home/travis/build/fluentmigrator/fluentmigrator/src/FluentM
igrator.Runner.Core/Infrastructure/DefaultMigrationConventions.cs:line 67
   at FluentMigrator.Runner.Initialization.ProfileSource.IsSelectedProfile(Type type, String profile) in /home/travis/build/fluentmigrator/fluentmigrator/src/FluentMigra
tor.Runner.Core/Initialization/ProfileSource.cs:line 55
   at System.Linq.Utilities.<>c__DisplayClass1_0`1.<CombinePredicates>b__0(TSource x)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.ToList()
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at FluentMigrator.Runner.ProfileLoader..ctor(IOptions`1 options, IProfileSource source, IServiceProvider serviceProvider) in /home/travis/build/fluentmigrator/fluentm
igrator/src/FluentMigrator.Runner/ProfileLoader.cs:line 63
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at FluentMigrator.Runner.Initialization.TaskExecutor.RunnerScope..ctor(TaskExecutor executor) in /home/travis/build/fluentmigrator/fluentmigrator/src/FluentMigrator.R
unner/Initialization/TaskExecutor.cs:line 253
   at FluentMigrator.Runner.Initialization.TaskExecutor.Execute() in /home/travis/build/fluentmigrator/fluentmigrator/src/FluentMigrator.Runner/Initialization/TaskExecut
or.cs:line 157
   at FluentMigrator.DotNet.Cli.Commands.BaseCommand.ExecuteMigrations(MigratorOptions options, IConsole console) in /home/travis/build/fluentmigrator/fluentmigrator/src
/FluentMigrator.DotNet.Cli/Commands/BaseCommand.cs:line 32
   at FluentMigrator.DotNet.Cli.Commands.Migrate.OnExecute(IConsole console) in /home/travis/build/fluentmigrator/fluentmigrator/src/FluentMigrator.DotNet.Cli/Commands/M
igrate.cs:line 35
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.Invoke(MethodInfo method, Object instance, Object[] arguments) in C:\projects\commandlineu
tils\src\CommandLineUtils\Conventions\ExecuteMethodConvention.cs:line 86
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.OnExecute(ConventionContext context) in C:\projects\commandlineutils\src\CommandLineUtils\
Conventions\ExecuteMethodConvention.cs:line 64
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.<>c__DisplayClass0_0.<<Apply>b__0>d.MoveNext() in C:\projects\commandlineutils\src\Command
LineUtils\Conventions\ExecuteMethodConvention.cs:line 25
--- End of stack trace from previous location where exception was thrown ---
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.<>c__DisplayClass126_0.<OnExecute>b__0() in C:\projects\commandlineutils\src\CommandLineUtils\CommandLi
neApplication.cs:line 505
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.Execute[TApp](CommandLineContext context) in C:\projects\commandlineutils\src\CommandLineUtils\CommandL
ineApplication.Execute.cs:line 31
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.Execute[TApp](IConsole console, String[] args) in C:\projects\commandlineutils\src\CommandLineUtils\Com
mandLineApplication.Execute.cs:line 97
   at FluentMigrator.DotNet.Cli.Program.Main(String[] args) in /home/travis/build/fluentmigrator/fluentmigrator/src/FluentMigrator.DotNet.Cli/Program.cs:line 35

Even though that FSharp.Core.dll is there. Strange.

nojaf commented 6 years ago

Okay, silly me. I've solved my own problem. Turns out my project is still targeting netcoreapp2.0 and all new global cli tools are netcoreapp2.1 by default. Which makes sense that it couldn't find my FSharp.Core.dll.

I've made a sample project using netcoreapp2.1, did a publish, installed dotnet-fm as a local tool in my publish folder and was able to execute the migration.

jzabroski commented 4 years ago

I will try to take on adding an F# sample project. I think we should only support the In Process Runner for F#. My reasoning is that I hate F# despite knowing the language. While it has its niche uses, I cannot stand how often the F# compiler crashes on me when using it in large solutions with dozens of C# projects. I do not want to have to guess which is the problem someone is having - bad F# compiler or FluentMigrator.

Edit: As of Visual Studio 2019 16.5, F# compiler seems much more faster and stable. Still, bad sentiment remains.

voroninp commented 4 years ago

Looks like this is a never ending story =(

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'FSharp.Core, Version=4.7.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
   at System.ModuleHandle.ResolveType(RuntimeModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type)
   at System.ModuleHandle.ResolveTypeHandleInternal(RuntimeModule module, Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
   at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
   at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(CustomAttributeRecord caRecord, MetadataImport scope, Assembly& lastAptcaOkAssembly, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, Object[] attributes, IList derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctor, Boolean& ctorHasParameters, Boolean& isVarArg)
   at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType, Boolean mustBeInheritable, IList derivedAttributes)
   at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeType type, RuntimeType caType, Boolean inherit)
   at System.Attribute.GetCustomAttributes(MemberInfo element, Type type, Boolean inherit)
   at System.Reflection.CustomAttributeExtensions.GetCustomAttributes[T](MemberInfo element)
   at FluentMigrator.Runner.Infrastructure.DefaultMigrationRunnerConventions.TypeIsProfileImpl(Type type) in /home/travis/build/fluentmigrator/fluentmigrator/src/FluentMigrator.Runner.Core/Infrastructure/DefaultMigrationConventions.cs:line 67
   at FluentMigrator.Runner.Initialization.ProfileSource.IsSelectedProfile(Type type, String profile) in /home/travis/build/fluentmigrator/fluentmigrator/src/FluentMigrator.Runner.Core/Initialization/ProfileSource.cs:line 55
   at System.Linq.Utilities.<>c__DisplayClass1_0`1.<CombinePredicates>b__0(TSource x)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.ToList()
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at FluentMigrator.Runner.ProfileLoader..ctor(IOptions`1 options, IProfileSource source, IServiceProvider serviceProvider) in /home/travis/build/fluentmigrator/fluentmigrator/src/FluentMigrator.Runner/ProfileLoader.cs:line 63
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at FluentMigrator.Runner.Initialization.TaskExecutor.RunnerScope..ctor(TaskExecutor executor) in /home/travis/build/fluentmigrator/fluentmigrator/src/FluentMigrator.Runner/Initialization/TaskExecutor.cs:line 253
   at FluentMigrator.Runner.Initialization.TaskExecutor.Execute() in /home/travis/build/fluentmigrator/fluentmigrator/src/FluentMigrator.Runner/Initialization/TaskExecutor.cs:line 157
   at FluentMigrator.DotNet.Cli.Commands.BaseCommand.ExecuteMigrations(MigratorOptions options, IConsole console) in /home/travis/build/fluentmigrator/fluentmigrator/src/FluentMigrator.DotNet.Cli/Commands/BaseCommand.cs:line 32
--- End of stack trace from previous location where exception was thrown ---
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.Invoke(MethodInfo method, Object instance, Object[] arguments)
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.OnExecute(ConventionContext context)
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.<>c__DisplayClass0_0.<<Apply>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.<>c__DisplayClass142_0.<OnExecute>b__0()
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.Execute[TApp](CommandLineContext context)
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.Execute[TApp](IConsole console, String[] args)
   at FluentMigrator.DotNet.Cli.Program.Main(String[] args) in /home/travis/build/fluentmigrator/fluentmigrator/src/FluentMigrator.DotNet.Cli/Program.cs:line 35
jzabroski commented 4 years ago

Can you try using the In Process Runner? And compare .deps.json if it works

jzabroski commented 4 years ago

The other thing to be mindful of when getting dll not found errors is that it's possible you'e actually loading the wrong dll. To check, use dotPeek or Reflector to spy on the assembly file's manifest section and see the true version of the dll. This isn't obvious because IDEs like Visual Studio still dont do a great job surfacing this level of detail to users - they surface the PackageReference Version, not the AssemblyVersionAttribute metadata that gets woven into the PE header.

voroninp commented 4 years ago

I created the side C# project and was able to load the published assembly and scan all attributes. I'll add in-proc runner, and let you know whether it works.

voroninp commented 4 years ago

Im-proc runner works fine, and I cannot spot any difference between .deps.json. ='(

jzabroski commented 4 years ago

@voroninp It is very likely its a subtle issue with the PE manifest linking the wrong dll internally. I've written about this extensively but in no single place. I ran into such issues using System.ComponentModel.DataAnnotations with a netstandard2.0 project that was consumed by net48 and .netcoreapp2.2. A lot of people I think get tripped up by this and its a PITA to debug. The only way I got to the bottom of it was I was working Christmas day through New Years Eve instead of celebrating the holidays.

I dont know how the FSharp team packaged FSharp.Core but I recall being upset with how they did it in the older days so it wouldn't surprise me if the DLL copied into your folder is actually FSharp.Core.dll v 4.7.1 despite being linked as 4.7.0, or similar.

cartermp commented 4 years ago

(found this from SO)

When using the .NET SDK (or any new "legacy" project as of VS 16.0) the FSharp.Core binary is a package. Things used to be absolutely nightmarish with FSharp.Core in the GAC, then not in the GAC, then at least three different ones depending on what you were doing (.NET Core 1.x was great). But now it's just the package for anything build with VS 2019 or from .NET Core.

Since versioning could only ever be horribly complicated, here's a full breakdown of the various versions and what they mean.

Currently the numbers should be:

AssemblyVersion: 4.7.0.0
FileVersion: 4.700.20.10408
ProductVersion: 4.7.0-beta.20104.8+7c4de19faf36647c1ef700e655a52350840c6f03

So the versions @voroninp reports in the deps.json in the SO question appear to line up.

The FSharp.Core binary itself is laid out under FSharp.Core.4.7.1/lib/tfm/FSharp.Core.dll and that's been the format ever since it's been distributed via NuGet. I doubt that will change, though we will be dropping the net45 binary in F# 5/.NET 5.

jzabroski commented 4 years ago

@cartermp Very helpful as usual, thanks. @voroninp It would probably be helpful to log the output of System.AppContext.GetData(“APP_CONTEXT_DEPS_FILES”) to ensure the deps.json file you think is being loaded, is actually being loaded. I'm not sure if .NET Core CLI Tools can accept --additionalprobingpath option

voroninp commented 4 years ago

@jzabroski you mean, checking this for in-proc runner?

Interesting though, wen I run migrator cli locally from Visual Studio (forked and checked out) if fails in constructor of AssemblySourceMigrationRunnerConventionsAccessor when getting exported types of assemblies:

System.IO.FileLoadException: 'Could not load file or assembly 'FluentMigrator, Version=3.2.1.0, Culture=neutral, PublicKeyToken=aacfc7de5acabf05'. Could not find or load a specific file. (0x80131621)' at System.Reflection.RuntimeAssembly.GetExportedTypes() at FluentMigrator.Runner.Initialization.AssemblySourceMigrationRunnerConventionsAccessor.<>c.<.ctor>b1_1(Assembly a) in C:\Users\pavelvoronin\Source\Repos\fluentmigrator\src\FluentMigrator.Runner.Core\Initialization\AssemblySourceMigrationRunnerConventionsAccessor.cs:line 50 at System.Linq.Enumerable.SelectManySingleSelectorIterator2.MoveNext() at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable1 source, Func2 predicate, Boolean& found) at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable1 source, Func`2 predicate) at FluentMigrator.Runner.Initialization.AssemblySourceMigrationRunnerConventionsAccessor.<>c__DisplayClass1_0.<.ctor>b0() in C:\Users\pavelvoronin\Source\Repos\fluentmigrator\src\FluentMigrator.Runner.Core\Initialization\AssemblySourceMigrationRunnerConventionsAccessor.cs:line 50 at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)

jzabroski commented 4 years ago

@voroninp

you mean, checking this for in-proc runner?

Yes. We should probably also patch dotnet-fm to have a debug logging that dumps this stuff, too. Good question. I'll create a ticket for that now.

Basically, I am trying to improve my customer service script for debugging these issues. I have debugged a lot of them through this project and another project I help with, RazorLight. I'm certainly borrowing some ideas from @cartermp here as well. (However, the end result for me is the same: I spend a lot of time debugging people's link-and-load issues with .NET Core, and it's killing my productivity in terms of delivering features and product improvements. I saw NickCraver from StackOverflow joke on Twitter about how hard these problems are to solve, but I think the projects I work on are particularly tricky and I've explored a lot of permutations to try to find the best/simple solution for all.).

Just so you know: A dirty workaround for not being able to locate the assembly is to have a DirtyAssemblyResolveHelper class in your project and load it as part of a Maintenance BeforeAll migration (or, if you're using In-Process Runner, you can just add the DirtyAssemblyResolveHelper before your FM logic). DirtyAssemblyResolveHelper is a common design pattern in tools like MSBuild, Fody, and BenchmarkDotNet. You do have to be careful about creating infinite loops trying to resolve dependencies, though.

jzabroski commented 4 years ago

Created #1197 to log the deps.json file context if user passes in command line flag to the tool.

jzabroski commented 4 years ago

@voroninp Btw, did you try the steps mentioned by @nojaf here:

  1. Uninstall dotnet-fm (to ensure its not installed as a global tool)
  2. Install dotnet-fm against your target sdk (perhaps via a tool manifest instead of via global tool)

In terms of running dotnet-fm, now that .netcore 3.0 supports tool manifests, maybe the documentation should be updated to encourage that instead of global tools.

Off top of my head, I'm not sure how to determine what runtime a global tool runs against. But, due to the fact the default behavior of DotNet RollForward is MinorVersion, if you installed the tool against dotnet 3.0 and later installed dotnet 3.1, the tool will probably break, IIRC. Just another thing to add to the customer service script.

voroninp commented 4 years ago

For the runner the output is:

...\DbMigrationsRunner\bin\Debug\netcoreapp3.1\DbMigrationsRunner.deps.json; C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.2\Microsoft.NETCore.App.deps.json

And runner does not reference the project, it just load the assembly:

let assembly = Assembly.LoadFrom("../../../../DbMigrations/bin/Debug/netcoreapp3.1/DbMigrations.dll");
voroninp commented 4 years ago

@jzabroski ooops

dotnet tool list -g

Package Id Version Commands
dotnet-ef 3.0.0 dotnet-ef
dotnet-encrypto 1.1.1 dotnet-encrypto
dotnet-httprepl 2.2.0-rtm-35542 dotnet-httprepl
dotnet-reportgenerator-globaltool 4.5.0 reportgenerator
fluentmigrator.dotnet.cli 3.2.1 dotnet-fm

But here example uses it as global tool.

jzabroski commented 4 years ago

I think that's the problem.

But here example uses it as global tool.

Yes, it's a bit out-dated since it was written for .NET Core 2.1 when global tools were introduced. We also didn't realize the versioning issue with .NET Core Global Tools until .NET Core 2.2 came out, and not everyone was even using .NET Core 2.2, including myself. I skipped straight to 3.0, so I never encountered the problems until I skipped from 3.0 to 3.1.

voroninp commented 4 years ago

Alas, same error both for locally installed tool and for globally installed one targeted .net core 3.1 ='(

cartermp commented 4 years ago

@jzabroski Unfortunately I don't have anything meaningful to add here, just wanted to acknowledge that this kind of work is really difficult and I think it's great you do it, despite the frustrations involved.

jzabroski commented 4 years ago

@voroninp I think the remaining issue is we need to release FluentMigrator 3.2.2 - it's on AzureDevOps but not published to Nuget.org since I got overrun by COVID-19 Disaster Recovery Planning. The back story is I had many attempts at trying to get RollForward to work correctly, and despite getting guidance from Nick Geurrera at Microsoft (who effectively authored the RollForward design), I realized the best approach was to abandon #1139 because it causes weird link-and-load issues. The trade-off is all the builds/nuget packages are slower/larger now, but it really does seem to be the best development experience for the end user.

jzabroski commented 4 years ago

@cartermp No worries - and I hope my comments about disliking F# are not taken personally. I was a huge fan of F# in the early days but just gave up the evangelism battle, especially when I ran into stability issues. Still hope F# teaches the CLR team to think more robustly about the CLR type system.

jzabroski commented 4 years ago

Alas, same error both for locally installed tool and for globally installed one targeted .net core 3.1 ='(

By the way, locally installed tool is not exactly the same thing as a .net tool manifest approach. I can't remember all the details but they are indeed different. Did you do local tool install or did you do the tool manifest approach?

voroninp commented 4 years ago

It looks like since 3.1 it is the same. I wasn't able to install locally until I created tool manifest. Or do miss something?

jzabroski commented 4 years ago

https://dev.azure.com/fluentmigrator/fluentmigrator/_packaging?_a=connect&feed=fluentmigrator

3.2.4 is in this feed - can you try connecting to it? Not sure if you have view access to this page, but I think its public.

EDIT: To understand why I think this will work, see 3.2.2 release notes: https://github.com/fluentmigrator/fluentmigrator/releases/tag/v3.2.2

EDIT: ACtually, I'm wrong, #1178 was never merged from my local copy. Wife has the laptop with those changes.

voroninp commented 4 years ago

@jzabroski , ok, now after updating to 3.2.4 from Azure feed I have consistent failure. Bot for the tool and when running migrator solution I get same error:

Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'FluentMigrator, Version=3.2.4.0, Culture=neutral, PublicKeyToken=aacfc7de5acabf05'. Could not find or load a specific file. (Exception from HRESULT: 0x80131621) ---> System.IO.FileLoadException: Could not load file or assembly 'FluentMigrator, Version=3.2.4.0, Culture=neutral, PublicKeyToken=aacfc7de5acabf05'.

jzabroski commented 4 years ago

I'm going to try to create a F# sample project in the next few days.

voroninp commented 4 years ago

@jzabroski A small one

jzabroski commented 4 years ago

@voroninp thanks, cloned, downloaded, any chance you can export your .vsconfig as well? https://docs.microsoft.com/en-us/visualstudio/install/command-line-parameter-examples?view=vs-2019#using-export

voroninp commented 4 years ago

Pushed it to repo as well

{
  "version": "1.0",
  "components": [
    "Microsoft.VisualStudio.Component.CoreEditor",
    "Microsoft.VisualStudio.Workload.CoreEditor",
    "Microsoft.NetCore.Component.Runtime.3.1",
    "Microsoft.NetCore.Component.SDK",
    "Microsoft.VisualStudio.Component.NuGet",
    "Microsoft.Net.Component.4.6.1.TargetingPack",
    "Microsoft.VisualStudio.Component.Roslyn.Compiler",
    "Microsoft.VisualStudio.Component.Roslyn.LanguageServices",
    "Microsoft.VisualStudio.Component.FSharp",
    "Microsoft.NetCore.Component.DevelopmentTools",
    "Microsoft.VisualStudio.Component.FSharp.WebTemplates",
    "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions",
    "Microsoft.VisualStudio.Component.DockerTools",
    "Microsoft.NetCore.Component.Web",
    "Microsoft.Net.Component.4.8.SDK",
    "Microsoft.Net.Component.4.7.2.TargetingPack",
    "Microsoft.Net.ComponentGroup.DevelopmentPrerequisites",
    "Microsoft.VisualStudio.Component.TypeScript.3.8",
    "Microsoft.VisualStudio.Component.JavaScript.TypeScript",
    "Microsoft.VisualStudio.Component.JavaScript.Diagnostics",
    "Microsoft.Component.MSBuild",
    "Microsoft.VisualStudio.Component.TextTemplating",
    "Component.Microsoft.VisualStudio.RazorExtension",
    "Microsoft.VisualStudio.Component.IISExpress",
    "Microsoft.VisualStudio.Component.SQL.ADAL",
    "Microsoft.VisualStudio.Component.SQL.LocalDB.Runtime",
    "Microsoft.VisualStudio.Component.Common.Azure.Tools",
    "Microsoft.VisualStudio.Component.SQL.CLR",
    "Microsoft.VisualStudio.Component.MSODBC.SQL",
    "Microsoft.VisualStudio.Component.MSSQL.CMDLnUtils",
    "Microsoft.VisualStudio.Component.ManagedDesktop.Core",
    "Microsoft.Net.Component.4.5.2.TargetingPack",
    "Microsoft.Net.Component.4.5.TargetingPack",
    "Microsoft.VisualStudio.Component.SQL.SSDT",
    "Microsoft.VisualStudio.Component.SQL.DataSources",
    "Component.Microsoft.Web.LibraryManager",
    "Microsoft.VisualStudio.ComponentGroup.Web",
    "Microsoft.VisualStudio.Component.Web",
    "Microsoft.VisualStudio.Component.IntelliCode",
    "Microsoft.Net.Component.4.TargetingPack",
    "Microsoft.Net.Component.4.5.1.TargetingPack",
    "Microsoft.Net.Component.4.6.TargetingPack",
    "Microsoft.Net.ComponentGroup.TargetingPacks.Common",
    "Microsoft.Net.Core.Component.SDK.2.1",
    "Component.Microsoft.VisualStudio.Web.AzureFunctions",
    "Microsoft.VisualStudio.ComponentGroup.AzureFunctions",
    "Microsoft.VisualStudio.Component.Azure.Compute.Emulator",
    "Microsoft.VisualStudio.Component.Azure.Storage.Emulator",
    "Microsoft.VisualStudio.Component.Azure.ClientLibs",
    "Microsoft.VisualStudio.Component.Azure.AuthoringTools",
    "Microsoft.VisualStudio.Component.CloudExplorer",
    "Microsoft.VisualStudio.ComponentGroup.Web.CloudTools",
    "Microsoft.VisualStudio.Component.DiagnosticTools",
    "Microsoft.VisualStudio.Component.EntityFramework",
    "Microsoft.VisualStudio.Component.AspNet45",
    "Microsoft.VisualStudio.Component.AppInsights.Tools",
    "Microsoft.VisualStudio.Component.WebDeploy",
    "Microsoft.VisualStudio.Component.Debugger.JustInTime",
    "Microsoft.Net.Component.4.6.2.TargetingPack",
    "Microsoft.Net.Component.4.7.TargetingPack",
    "Microsoft.Net.Component.4.7.1.TargetingPack",
    "Microsoft.Net.Component.4.8.TargetingPack",
    "Microsoft.VisualStudio.Workload.NetWeb",
    "Microsoft.VisualStudio.ComponentGroup.Azure.Prerequisites",
    "Microsoft.VisualStudio.Component.Azure.Waverton.BuildTools",
    "Microsoft.VisualStudio.Component.Azure.Waverton",
    "Microsoft.Component.Azure.DataLake.Tools",
    "Microsoft.VisualStudio.Component.Azure.Kubernetes.Tools",
    "Microsoft.VisualStudio.Component.Azure.ResourceManager.Tools",
    "Microsoft.VisualStudio.ComponentGroup.Azure.ResourceManager.Tools",
    "Microsoft.VisualStudio.ComponentGroup.Azure.CloudServices",
    "Microsoft.VisualStudio.Component.Azure.ServiceFabric.Tools",
    "Microsoft.VisualStudio.Workload.Azure",
    "Microsoft.Component.PythonTools",
    "Microsoft.Component.PythonTools.Miniconda",
    "Microsoft.Component.PythonTools.Web",
    "Microsoft.VisualStudio.Component.VC.CoreIde",
    "Microsoft.VisualStudio.Component.Windows10SDK",
    "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
    "Microsoft.VisualStudio.Component.Graphics.Tools",
    "Microsoft.VisualStudio.Component.VC.DiagnosticTools",
    "Microsoft.VisualStudio.Component.Windows10SDK.18362",
    "Microsoft.ComponentGroup.PythonTools.NativeDevelopment",
    "Component.CPython3.x64",
    "Component.CPython3.x86",
    "Microsoft.VisualStudio.Workload.Python",
    "Microsoft.VisualStudio.Component.Node.Tools",
    "Microsoft.VisualStudio.Workload.Node",
    "Microsoft.VisualStudio.Component.ManagedDesktop.Prerequisites",
    "Microsoft.ComponentGroup.Blend",
    "Microsoft.VisualStudio.Component.FSharp.Desktop",
    "Component.Dotfuscator",
    "Microsoft.VisualStudio.Component.PortableLibrary",
    "Microsoft.VisualStudio.ComponentGroup.MSIX.Packaging",
    "Microsoft.VisualStudio.Workload.ManagedDesktop",
    "Microsoft.VisualStudio.Component.VC.Redist.14.Latest",
    "Microsoft.VisualStudio.Component.Windows10SDK.17763",
    "Microsoft.Component.NetFX.Native",
    "Microsoft.VisualStudio.ComponentGroup.UWP.NetCoreAndStandard",
    "Microsoft.VisualStudio.Component.Graphics",
    "Microsoft.VisualStudio.ComponentGroup.UWP.Xamarin",
    "Microsoft.VisualStudio.ComponentGroup.UWP.Support",
    "Microsoft.VisualStudio.Workload.Universal",
    "Component.OpenJDK",
    "Microsoft.VisualStudio.Component.MonoDebugger",
    "Microsoft.VisualStudio.Component.Merq",
    "Component.Xamarin.RemotedSimulator",
    "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions.TemplateEngine",
    "Component.Xamarin",
    "Component.Android.SDK28",
    "Component.Android.SDK25.Private",
    "Microsoft.Net.Component.3.5.DeveloperTools",
    "Microsoft.VisualStudio.Component.Unity",
    "Component.UnityEngine.x86",
    "Microsoft.VisualStudio.Workload.ManagedGame",
    "Microsoft.VisualStudio.Component.NuGet.BuildTools",
    "Microsoft.VisualStudio.Workload.Data",
    "Microsoft.VisualStudio.Workload.DataScience",
    "Microsoft.VisualStudio.Component.VSSDK",
    "Microsoft.VisualStudio.Component.DslTools",
    "Microsoft.Component.CodeAnalysis.SDK",
    "Microsoft.VisualStudio.Workload.NetCoreTools",
    "Microsoft.Component.HelpViewer",
    "Microsoft.VisualStudio.Component.Git",
    "Microsoft.VisualStudio.Component.ClassDesigner",
    "Microsoft.VisualStudio.Component.DependencyValidation.Community",
    "Component.Xamarin.Workbooks",
    "Microsoft.Net.Core.Component.SDK.2.2",
    "Microsoft.NetCore.ComponentGroup.DevelopmentTools.2.1",
    "Microsoft.NetCore.ComponentGroup.Web.2.1",
    "Microsoft.VisualStudio.Component.AzureDevOps.OfficeIntegration",
    "Microsoft.Component.ClickOnce",
    "Microsoft.Net.Component.4.6.1.SDK",
    "Microsoft.Net.Component.4.6.2.SDK",
    "Microsoft.Net.Component.4.7.SDK",
    "Microsoft.Net.Component.4.7.1.SDK",
    "Microsoft.Net.Component.4.7.2.SDK"
  ]
}
jzabroski commented 4 years ago

@voroninp I spent my Saturday evening putting together a sample of an F# In-Process Runner using FluentMigrator. I am by no means an F# expert and last wrote F# code in January as part of a project to port F# logic to C#. In particular, I found some of the syntax F# seemed to require me to write to interface with C# logic:

  1. Weird conventions around how F# auto-getters and setters work - why do I have to define the type twice, and why does it only work well if I define the initial value via type constructor (I think this is because you have to allocate some value, but it wasn't clear from the F# documentation)
  2. Wrapping Action<T> requires extra type parameter noise compared to C# (surprisingly)

However, I can guarantee you I got this working. Please see: https://github.com/jzabroski/FSharpFluentMigratorCli/tree/master

Up next to is to debug the issues with running this from Fake, but for that I need more information from @tylerhartwig please.

BTW, @cartermp - if interested, feel free to code review and correct me if my above experience is based on amateurish insight :)

jzabroski commented 4 years ago

@tylerhartwig Coming back to your original comments:

Migrations defined in F# fail to be discovered by FluentMigrator when defined in F#.

I have tested this a plethora of ways from F#, each resulting in a different error.

  1. Running using FAKE a) When running without explicitly loading FluentMigrator and FluentMigrator.Abstractions into the load context, these assemblies cannot be found. b) When running with these explicitly loaded, a MissingMigrationsException is thrown, even though, to the best of my knowledge, the appropriate class is discoverable.

Since I'm not familiar with using Fake, can you please explain to me how you're using Fake? We have FluentMigrator.MSBuild package but it's a bit jacked up at the moment due to how things are packaged. It should approximately copy FluentMigrator.Console dependencies into FluentMigrator.MSBuild.

  1. Running out of process When running using the out of process tool, the tool fails to find FSharp.Core

I'm assuming by out of process tool, you're referring to dotnet-fm (FluentMigrator.DotNet.Cli), because you logged this issue on May 20th, 2018, shortly after .NET Global Tools were first announced. We created #1016 to capture various reasons why out-of-process tools fail. To the best of my knowledge, this is some of the better documentation in the .NET ecosystem for dealing with out-of-process tooling issues related to dynamically loading assemblies. That said, the fixes are not straight forward and my first attempts at "simple solutions" did not work. Rest assured, I've been in the shadows working on and off over the last two years on this problem.

Which brings me to your next comment:

  1. Running as a separate console application (defined in F#) When running in the separate console application, a SIGSEV is thrown.

With @voroninp help, I have provided a complete working console application that does not SIGSEV. Please let me know if this addresses your problem. Since there was no code provided with your original solution, and I don't even know what a SIGSEV is, I can't really investigate why you ran into this problem further (maybe you were targeting .NET Framework 4.6.1?). However, I can explain why "Running as a separate console application (defined in F#)" should be guaranteed to work. As I mentioned above, when you compile everything "in-process", it forces the .NET toolchain to generate a valid .deps.json file.

I don't think this library explicitly supports F#, and I understand that, however while result 1a seems weird, 1b is really what I'm opening an issue about.

For 1b, the MissingMigrationsException, I'm not sure without getting a Fake build tool repro. As I'm not aware with how you configured Fake, or familiar with Fake itself, I can't be of much help. That said, build tools are nasty things, and it could be you're simply running into issues loading things into a global assembly loading context. A lot of time has passed between you initially opening this issue and today, notably .NETCoreApp3.0, and robust support for multiple AssemblyLoadContexts. I imagine since Fake is written in F# that it is still bound by the laws of the CLR, and so that would be where you should focus future such investigations, whether its FluentMigrator or another project.

Again, always happy to help debug, but I need to know what to debug to help.

Happy fluent migrating!

voroninp commented 4 years ago

@jzabroski you do not have to specify type everywhere:

let action = Action<string>(fun x -> printfn "%s" x |> ignore)

or you may even do like this:

let action = Action<'a>(fun x -> printfn "%s" x |> ignore), though compiler will warn you that code becomes not that generic because type inference effectively narrows 'a to string due to %s modifier.

why do I have to define the type twice, a

What do you mean?

jzabroski commented 4 years ago

@jzabroski you do not have to specify type everywhere:

why do I have to define the type twice, a

What do you mean?

I was referring to this:

type DatabaseConfiguration(processorId : string, connectionString : string) =
     member val ProcessorId = processorId with get, set
     member val ConnectionString = connectionString with get, set

I figured it out - I can do member val ConnectionString : string = connectionString with get, set but can't do member val ConnectionString : string with get, set unless I specify a default value or provide a type constructor that initializes the value.

jzabroski commented 4 years ago

@jzabroski you do not have to specify type everywhere:

let action = Action<string>(fun x -> printfn "%s" x |> ignore)

or you may even do like this:

Alright, I pushed the latest version and cleaned it up a bit based on your suggestions. Let me know if you think this is a publishable F#-style, or if any other improvements are needed.

voroninp commented 4 years ago

It LGTM, but I am still curious how to debug dotnet-fm issue. ='(

voroninp commented 4 years ago

I switched DbMigrations to C# project. Now I have another error:

dotnet fm list migrations -p SqlServer -a .\DbMigrations\bin\Debug\netstandard2.0\DbMigrations.dll

System.ArgumentException: Format of the initialization string does not conform to specification starting at index 0.

When I provide connection string with -c , dotnet-fm shows migrations.

jzabroski commented 4 years ago

What project you use does not matter. As far as I'm aware, .deps.json isn't calculated/generated by the compiler, it's calculated by MSBuild.

Can you please provide a fuller stack trace? I can't see if there is an inner exception, or what line number this error even occurs on.

voroninp commented 4 years ago

System.ArgumentException: Format of the initialization string does not conform to specification starting at index 0. at System.Data.Common.DbConnectionOptions.GetKeyValuePair(String connectionString, Int32 currentPosition, StringBuilder buffer, String& keyname, String& keyvalue) at System.Data.Common.DbConnectionOptions.ParseInternal(Dictionary2 parsetable, String connectionString, Boolean buildChain, Dictionary2 synonyms) at System.Data.Common.DbConnectionOptions..ctor(String connectionString, Dictionary2 synonyms) at System.Data.SqlClient.SqlConnectionString..ctor(String connectionString) at System.Data.SqlClient.SqlConnectionFactory.CreateConnectionOptions(String connectionString, DbConnectionOptions previous) at System.Data.ProviderBase.DbConnectionFactory.GetConnectionPoolGroup(DbConnectionPoolKey key, DbConnectionPoolGroupOptions poolOptions, DbConnectionOptions& userConnectionOptions) at System.Data.SqlClient.SqlConnection.ConnectionString_Set(DbConnectionPoolKey key) at System.Data.SqlClient.SqlConnection.set_ConnectionString(String value) at FluentMigrator.Runner.Processors.GenericProcessorBase.<>c__DisplayClass6_1.<.ctor>b__1() in d:\a\1\s\src\FluentMigrator.Runner.Core\Processors\GenericProcessorBase.cs:line 102 at System.Lazy1.ViaFactory(LazyThreadSafetyMode mode) at System.Lazy1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor) at System.Lazy1.CreateValue() at FluentMigrator.Runner.Processors.GenericProcessorBase.EnsureConnectionIsOpen() in d:\a\1\s\src\FluentMigrator.Runner.Core\Processors\GenericProcessorBase.cs:line 128 at FluentMigrator.Runner.Processors.SqlServer.SqlServerProcessor.Exists(String template, Object[] args) in d:\a\1\s\src\FluentMigrator.Runner.SqlServer\Processors\SqlServer\SqlServerProcessor.cs:line 195 at FluentMigrator.Runner.Processors.SqlServer.SqlServerProcessor.TableExists(String schemaName, String tableName) in d:\a\1\s\src\FluentMigrator.Runner.SqlServer\Processors\SqlServer\SqlServerProcessor.cs:line 144


VersionMigration migrating

Unhandled Exception: System.ArgumentException: Format of the initialization string does not conform to specification starting at index 0. at System.Data.Common.DbConnectionOptions.GetKeyValuePair(String connectionString, Int32 currentPosition, StringBuilder buffer, String& keyname, String& keyvalue) at System.Data.Common.DbConnectionOptions.ParseInternal(Dictionary2 parsetable, String connectionString, Boolean buildChain, Dictionary2 synonyms) at System.Data.Common.DbConnectionOptions..ctor(String connectionString, Dictionary2 synonyms) at System.Data.SqlClient.SqlConnectionString..ctor(String connectionString) at System.Data.SqlClient.SqlConnectionFactory.CreateConnectionOptions(String connectionString, DbConnectionOptions previous) at System.Data.ProviderBase.DbConnectionFactory.GetConnectionPoolGroup(DbConnectionPoolKey key, DbConnectionPoolGroupOptions poolOptions, DbConnectionOptions& userConnectionOptions) at System.Data.SqlClient.SqlConnection.ConnectionString_Set(DbConnectionPoolKey key) at System.Data.SqlClient.SqlConnection.set_ConnectionString(String value) at FluentMigrator.Runner.Processors.GenericProcessorBase.<>c__DisplayClass6_1.<.ctor>b__1() in d:\a\1\s\src\FluentMigrator.Runner.Core\Processors\GenericProcessorBase.cs:line 102 at System.Lazy1.ViaFactory(LazyThreadSafetyMode mode) --- End of stack trace from previous location where exception was thrown --- at System.Lazy1.CreateValue() at FluentMigrator.Runner.Processors.GenericProcessorBase.EnsureConnectionIsOpen() in d:\a\1\s\src\FluentMigrator.Runner.Core\Processors\GenericProcessorBase.cs:line 128 at FluentMigrator.Runner.Processors.GenericProcessorBase.BeginTransaction() in d:\a\1\s\src\FluentMigrator.Runner.Core\Processors\GenericProcessorBase.cs:line 146 at FluentMigrator.Runner.Processors.SqlServer.SqlServerProcessor.BeginTransaction() in d:\a\1\s\src\FluentMigrator.Runner.SqlServer\Processors\SqlServer\SqlServerProcessor.cs:line 114 at FluentMigrator.Runner.MigrationScopeHandler.BeginScope() in d:\a\1\s\src\FluentMigrator.Runner\MigrationScopeHandler.cs:line 48 at FluentMigrator.Runner.MigrationRunner.ApplyMigrationUp(IMigrationInfo migrationInfo, Boolean useTransaction) in d:\a\1\s\src\FluentMigrator.Runner\MigrationRunner.cs:line 594 at FluentMigrator.Runner.VersionLoader.LoadVersionInfo() in d:\a\1\s\src\FluentMigrator.Runner\VersionLoader.cs:line 180 --- End of stack trace from previous location where exception was thrown --- at Microsoft.Extensions.Internal.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider) at Microsoft.Extensions.Internal.ActivatorUtilities.CreateInstance[T](IServiceProvider provider, Object[] parameters) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProvider provider) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at System.Lazy1.ViaFactory(LazyThreadSafetyMode mode) at System.Lazy1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor) at System.Lazy1.CreateValue() at FluentMigrator.Runner.MigrationRunner.ListMigrations() in d:\a\1\s\src\FluentMigrator.Runner\MigrationRunner.cs:line 908 at FluentMigrator.Runner.Initialization.TaskExecutor.Execute() in d:\a\1\s\src\FluentMigrator.Runner\Initialization\TaskExecutor.cs:line 172 at FluentMigrator.DotNet.Cli.Commands.BaseCommand.ExecuteMigrations(MigratorOptions options, IConsole console) in d:\a\1\s\src\FluentMigrator.DotNet.Cli\Commands\BaseCommand.cs:line 32 --- End of stack trace from previous location where exception was thrown --- at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.Invoke(MethodInfo method, Object instance, Object[] arguments) at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.OnExecute(ConventionContext context) at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.<>cDisplayClass0_0.<b0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at McMaster.Extensions.CommandLineUtils.CommandLineApplication.<>cDisplayClass142_0.b0() at McMaster.Extensions.CommandLineUtils.CommandLineApplication.Execute[TApp](CommandLineContext context) at McMaster.Extensions.CommandLineUtils.CommandLineApplication.Execute[TApp](IConsole console, String[] args) at FluentMigrator.DotNet.Cli.Program.Main(String[] args) in d:\a\1\s\src\FluentMigrator.DotNet.Cli\Program.cs:line 35

jzabroski commented 4 years ago

GenericProcessorBase.cs should probably pass the connection string into a connection string builder to provide a better error message. However, this error indicates that the issue is simply that you didn't tell it the connection string.

In this case, please:

  1. open a bug for "dotnet-fm list migrations shouldn't require connection string". I think this is a separate issue. The workaround is to supply a connection string to a database.
  2. (Possibly) Open a feature request for list migrations command with more options, such as listing migrations available vs. migrations not yet applied to a target database (which would require a connection string). Please provide feedback here on whether you think this is needed.
jzabroski commented 4 years ago

@tylerhartwig @voroninp I just realized Tyler's original post referencing Fake is probably refering to FAKE.FluentMigrator Nuget package. This is an external dependency. Willing to help get it working, but I need a repro.

jzabroski commented 3 years ago

Considering this closed as there is a sample on how to load migrations when defined in F#.