Fluentmigrator: Why is in-process runner preferred? [question]

Created on 26 Mar 2019  路  7Comments  路  Source: fluentmigrator/fluentmigrator

Hi,

I'm curious to know more about that reasoning behind the comment in the _Migration runners docs_ saying (https://fluentmigrator.github.io/articles/migration-runners.html?tabs=vs-pkg-manager-console):

Please use the in-process runner if possible.

What are the pros and cons with using the in-process instead of for example the _dotnet tool_?

Think would usually be a question for stack overflow or similar, but since the docs so clearly recommends an approach over another, it would be nice with some comments on why 馃槉

question

Most helpful comment

TL/DR: DLL dependencies are a real problem when using the external runners.

Long version:

The main reason why I recommend the in-process runner is, that running the migrations from your own application works better than using the external migration runner. The external runners use a simplistic approach to find all migrations (DLL dependencies) and sometimes fail when they're unable to find all dependencies.

Advantages of the in-process runner:

  • Works (no problems with dependent DLLs)
  • Fully customizable (external runners may not expose all features)
  • No external tools required, everything works out-of-the-box
  • Not all DLLs for all databases supported by FluentMigrator need to be published with your program

Advantages of the external runners:

  • DB migrations can be run during the installation process
  • Migrations can be kept separate from the main application

The advantages of one are the disadvantages of the other 馃榿 .

All 7 comments

TL/DR: DLL dependencies are a real problem when using the external runners.

Long version:

The main reason why I recommend the in-process runner is, that running the migrations from your own application works better than using the external migration runner. The external runners use a simplistic approach to find all migrations (DLL dependencies) and sometimes fail when they're unable to find all dependencies.

Advantages of the in-process runner:

  • Works (no problems with dependent DLLs)
  • Fully customizable (external runners may not expose all features)
  • No external tools required, everything works out-of-the-box
  • Not all DLLs for all databases supported by FluentMigrator need to be published with your program

Advantages of the external runners:

  • DB migrations can be run during the installation process
  • Migrations can be kept separate from the main application

The advantages of one are the disadvantages of the other 馃榿 .

@fredrik-lundin I was wondering the same thing. Thanks for asking.

@fubar-coder Would it be far to say that Nate McMaster's blog post about what's broken with .NET Assembly loading in older versions of .NET applies to MSBuild (aka "external runners")? In essence, the issue is not external runners vs. in-process runners, and everything to do with how bad the "assembly loading experience" is with external runners like MSBuild, since:

  1. External Runners like MSBuild don't support bindingRedirect(s)
  2. There are two distinct problems to solve with assembly binding: locating the assembly, and loading it. Due to how the CLR is architected, the assembly has to be loaded or an expression will raise a TypeLoadException if the assembly hasn't been loaded in time.

Bonus: https://docs.microsoft.com/en-us/dotnet/standard/assembly/unloadability-howto

@jzabroski Interesting. I haven't seen this blog post before. Maybe it can solve some of the problems I encountered. I'm willing to give this a shot. This would be only a partial fix, because this would only work with the dotnet-fm tool (with netstandard or netcoreapp assemblies), but not with the msbuild runner or with .NET Framework assemblies.

@fubar-coder My current "system's thinking" is that MSBuild gives me two key features (only one of which I need for FluentMigrator):

  1. Ability to take an object graph of items and shred the object graph into "span(s)" of "work" modeled as a concurrent work-stealing deque. Originally, this logic in MSBuild was developed by the Microsoft Robotics team inside Microsoft Research as the "Concurrency and Coordinate Runtime" (cf 2005). If you click the link, you will see George demoing "concurrent msbuild" back in 2005 and showing that this "concurrent msbuild" feature was actually built by George's Advanced Strategies group, not by MSBuild.
  2. Ability to have semantic logging with ANSI-colored output, in conjunction with advanced log view utility MSBuild Log Viewer

    • MSBuild Log Viewer is the closest tool to SmartInspect's GUI for viewing log files; it's a blend of SmartInspect and OverOps' Error Analysis

    • This is the "killer feature" and why we want to use MSBuild runner. The problem with just using dotnet-fm is that MSBuild takes output from any generic "Task" as plain output and strips the colors, and so since we currently use MSBuild to orchestrate tasks, we are locked into using the MSBuild runner so that we can output things in color. If you have a solution to this problem, I am all ears.

    • Long-term, our plan is to move to just using dotnet cli for everything, and I believe some combination of https://github.com/adamralph/bullseye and https://github.com/dotnet/command-line-api and https://github.com/dotnet/cli will allow me to break free from MSBuild entirely. However, while it is less than a month of work, squeezing that (unpaid) time in (and paying the bills) is always the challenge.

I fear that I have to do something similar like what the Entity Framework project does to execute the migrations, but I haven't looked in detail how they achieve .NET Framwork / .NET Core version independence.

I didn't know about the MSBuild Log Viewer. That would've been handy when finding problems on my old .NET Framework projects...

For MSBuild, our workaround is to define an old school packages.config containing the following package elements:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="FluentMigrator.Console" version="3.2.1" targetFramework="net461" />
  <package id="FluentMigrator.MSBuild" version="3.2.1" targetFramework="net461" />
</packages>

We then check into source control the packages/FluentMigrator.* directories to avoid complex bootstrap process.

Our DbMigrate MSBuild task then DependsOn="InstallTools", where InstallTools copies packages/FluentMigrator.MSBuild directory to packages/FluentMigrator.Console - this solves the problem where FluentMigrator.MSBuild is packaged as an old school ProjectName.NoReferences Nuget package. As the Sitecore maintainer points out , the better solution is to use <PrivateAssets>none</PrivateAssets> when you want to package FluentMigrator.MSBuild.NoReferences, and include the private assets (FluentMigrator.Console) for most users who just want the whole toolchain - and I am not sure there is a good use case for FluentMigrator.MSBuild.NoReferences.

Let me know if you follow me.

We may want to "reload" how we think about this question going forward, given Microsoft's announcement about .NET 5. This effectively kills off .NET Framework; .NET Framework 4.8 will likely be the last release of .NET Framework as we know it. I don't know why Microsoft didn't just come out and say that, but that is how I read Richard's press release Introducing .NET 5.

Was this page helpful?
0 / 5 - 0 ratings