Entity Framework Core with split migrations - entity-framework-core

I am in the process of migrating from EF6 and .Net Framework to EF Core and .Net.
Previously I had a solution for the data model (Data project below) that built and deployed to a nuget package
Solution
Data
SchemaX
...
SchemaY
...
...
Data.Migrations.SqlServer
Migrations
SchemaX
20220701110223_Migration1.cs
...
The data model can then be consumed by any number of separate jobs/apps/etc using the package. This worked fine using EF6. However, if I start again for EF Core I'm seeing the odd issue.
Using the package manager console with default project Data, I can type
add-migration -StartupProject "Data.Migrations.SqlServer" -Context "Data.SchemaXContext" -OutputDir "Migrations\\SchemaX" -Name:CoreInitial
and it will scaffold a migration. The migration ends up in the Data project due to this default. If I use the Data.Migrations.SqlServer as the target/default it cannot find the context - I assume there is something that I could put in this project (other than a reference) to point it in the right direction?
I'm basically trying to migrate frameworks and use the suggestion here to set a start point for core.
NB The Data.Migrations... project is used as the startup as the Data project is .Net Standard 2.0 targetted to allow for use in framework and .Net projects whereas the migrations project has been set to target Framework 4.8.
Edit
Removed the following as it has been fixed by use of the modelBuilder.Ignore<> directive to handle where contexts crossover.
However, what it scaffolds is not limited to the context provided - it basically scaffolds the entire database, all schemas/context items - and using this mechanism as it stands I cannot get it to reference a database for comparison like I could EF6 with it's connection string parameter. I'm not sure whether the scaffolding of the entire model is a configuration issue or the lack of start point database.

Related

Entity Framework 6 .net Framework Migrations / Package Management Console - How Do You Run These In An Azure Pipeline?

I am setting up an Azure Release Pipeline and I need to execute any pending DB Migrations as part of the release.
I have been scouring the internet for over an hour and everything I can find is about dotnet Core, while the database is EF6 on .Net Framework, not dotnet Core (I've done this several times before for Core).
The problem, as I see it, is that EF6 works using Visual Studio's built in Package Manager Console - This just doesn't exist in an Azure Pipeline; It's a Visual Studio weirdness.
There seems to be several ways I can skin this cat, in my head, but I can't figure out how to start with either of them within the context of the pipeline...
OPTION 1: Run the Migrations on the Pipeline - but... how?
OPTION 2: SQL Scripts - Requires running the Package Manager to generate them so they can be run (if I could do that on the pipeline then I'd just run it anyway so these would have to be created locally and committed with the code which is somewhat backward as a solution IMO)
OPTION 3: Write a console app - Do I really have to do this??
You can try Entity Framework Migration Extensions.
This task allows a Build / Release to provide database connection parameters and execute an Entity Framework 6 migration against the database.
Build your project to an output folder and include the migrate.exe executable that comes with Entity Framework 6.
Create an automated build that packages up your files and makes them accessible during a Release.
Create a Release definition for the relevant Build
Add an EF6 Migration task. Once that task is added to an environment within the release, you'll need to enter the appropriate parameters to configure it. All file path parameters should be within the file system for the build, none of them are for TFS source control paths.
You can also check this article.
The answer here is to use the ef6.exe command line tool and make sure it gets shipped with your build.
This could be useful to anyone here until Microsoft update the non-existent docs: http://github.com/dotnet/EntityFramework.Docs/issues/1740 - This contains a table with a kind of translation matrix between the two.

Resetting Entity Framework Migrations then synchronizing schemas from previous migrations

I am using Entity Framework 6.1.3 Data migrations along with code first.
I am in the process of resetting the migrations. I have deleted the migrations history table and created a new baseline snapshot of the current state of the db. Everything works fine on a new install with the following intializer:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<T>, Migrations.Configuration>(true));
However, how should one deploy this reset to our customers who have an existing database? This fails locally when i have an existing db with the error:
There is already an object named '*****' in the database.
Does anyone have a better approach when needing to reset migrations and synchronizing schemas of existing databases?
I set out thinking I needed to reset my migrations because previous developers on my team were not using the Add-Migrations script correctly. This was causing the following error:
However, I wasn't sure how that would work out for existing customers. I didn't realize that I was able to re-scaffold my migrations. After much SO searching and trial and error, I was able to save my migrations. I first migrated to a migrations that was in a good state.
It was important to use the fully qualified name given. After trial and error I found a stable migration. I verified this by running the following:
It would succeed if EF could fully reconcile. I also had to exclude from VS project, all the migrations following the recently targeted migration. Simple shift select, right click and exclude from project.
Then I added the next migration back to the project after i updated the database. I also used the fluent API to exclude all the model changes following the currently targeted migration.
Then I incrementally re-scaffold all the broken migrations.
Then at the very end I created an idempotent script of my schema up to this point. Using the following:
My migrations are now not complaining about model mismatch and I am happy.

How to execute EntityFramework CLI commands programmatically in .NET Core?

How to run those dotnet.exe ef <command> commands programmatically in .NET Core?
For example to add migration I'm running in terminal dotnet ef migrations add NewMigration and it will indeed create Migrations folder with migration classes, but to create new Migration (for example) programmatically from C# code?
Don't suggest Process.Start("cmd bla-bla") since code should be cross-platform and that dotnet ef runs some code from some EntityFrameworkCore package anyway. Question is what code?
EF Core API isn't really designed for the scenario, but if you want to do this anyways, you'll need to repeat the logic that "dotnet-ef.dll" does to gather project context and compilation output, and then instantiate and use MigrationsOperations manually.
See https://github.com/aspnet/EntityFramework/blob/1.0.0/src/Microsoft.EntityFrameworkCore.Design.Core/Design/MigrationsOperations.cs and https://github.com/aspnet/EntityFramework/blob/1.0.0/src/Microsoft.EntityFrameworkCore.Design/Internal/OperationExecutor.cs
Use caution: these are "Internal" APIs, which means their usage may break from version to version. "dotnet ef" is going to change a great deal between the current release (1.0.0-preview2) and the next release. (For example, the entire tooling implementation will change. See https://github.com/aspnet/EntityFramework/issues/5334).

How to cope with "No data stores are configured"?

I am currently playing with beta4 of EF7 using the blank ASP.NET web project template.
After having kicked off the existing migration, resulting in the tables being created in the localdb, the following occurs:
Strangely, when I clean up the migration-folder, including removing ApplicationDbContextModelSnapshot.cs and I run
dnx . ef migration add twice, I get the following error:
dnx : System.InvalidOperationException: No data stores are configured. Configure a data store by overriding OnConfiguring in your DbContext class or in the AddDbContext method when setting up services.
The second migration is not created. When I review the created migration it contains all tables whereas the database is already provisioned, so you should expect the migration being empty.
Then, when I remove the first migration and run the add migration command again more than once, all the migrations are correctly created, i.e. as empty files.
Can someone explain this to me? Is this expected behavior or is this a bug in beta4?
Tip for people coming from former EF-versions:
* Don't use the K command framework anymore.
* Don't use the Add-Migration cmdlets anymore.
Both have been replaced by dnx . (dot). (dnx = .NET execution environment)
Some references:
https://github.com/aspnet/EntityFramework/wiki/Entity-Framework-Design-Meeting-Notes---September-11,-2014
http://jameschambers.com/2015/05/project-k-dnvm-dnx-dnu-and-entity-framework-7-for-bonus-points/
Remove the constructor of ApplicationContext. It is a temporary workaround to enable deployment, but it interferes with the Migrations commands.

Creating initial migration for existing DB results in empty migration

I'm using EF 6.1.2. I have an existing database, and I've Enabled Migrations. When I enter the command AddMigration InitialCreate in the console, the migration that is created is empty. From what I can find researching, that's what should happen if I add the parameter -IgnoreChanges, but I'm not doing that.
Most of the Migrations documentation references EF 4.3. I haven't found anything that says it has changed for 6.1.2. Is there a new command parameter to force the migration to contain the create code? Or is something else missing in my configuration?
Thanks
My application is n-tiered with both a Web API and an MVC project. Because I have multiple start-up projects set, EF was not able to determine which application to use to find the start up configuration. I was applying the Add-Migrations to the Data Access layer but the connection string and entity framework initialization settings were in the MVC web.config. After I copied these to the App.Config of the data access layer, all worked as expected.