Entity Framework Database First - How to prevent running the initial migration? - c#

I was able to scaffold an existing database using EF Core recently. We want to completely migrate to EF Core, but we've hit some snags and I need your help.
We began by running the scaffold command and ended up with this file structure
C:\>ls .\EFCore
Context
Models
EFCore.csproj
Then after creatinng the Context and the Models, I ran the inital migration command.
dotnet ef migrations add CreateDb
After running that command our directories look like this
C:\>ls .\EFCore
Context
Models
Migrations
EFCore.csproj
C:\>ls .\EFCore\Migrations
20210616210256_CreateDb.cs
20210616210256_CreateDb.Designer.cs
DbContextModelSnapshot.cs
My Problem
The database is already created in all environments, so we don't want entity to execute the inital database migration. Should I delete 20210616210256_CreateDb.cs and 20210616210256_CreateDb.Designer.cs to achieve this?
The other route I can think of is create the __EFMigrationsHistory table and insert a row into it. This would fake that we've already ran the inital db create.
Help please, I would like to do this the cleanest way possible.

Remove/Comment the code inside your Up() and Down() methods of migration file and call update database. You don't want the code which creates table i.e.
CreateTable(
"dbo.YourTable",
c => new
{ //Properties set here })
Your migration class could look like this -
public partial class Initial : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}

Related

Updating a SQLite Database to reflect a change to the model with Entity Framework Core and .NET 6

I've created a dbcontext that looks like this:
public class DatabaseContext : DbContext
{
public DbSet<Author> Authors { get; set; }
public DbSet<Book> Books { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite(#"Data Source=E:\Portfolio\FullStack\HomeLibraryManager\Database\Library.db;");
}
}
And I Initialize it like this:
using (var context = new DatabaseContext())
{
context.Database.EnsureCreated();
var books = context.Books.ToList();
}
I would like to add a variable to my Book class but how do I get the database table to have that new variable added as a column.
I had hoped that EnsureCreated() would make sure the table columns were updated if needed but it seems not.
Any help would be great,
thanks
Edit Solution:
I used context.Database.Migrate(); instead of EnsureCreated and ran dotnet-ef migrations add [MigrationNameHere] first
Run the Add-Migration AddUrl command in Package Manager Console. The Add-Migration command checks for changes since your last migration and scaffolds a new migration with any changes that are found. We can give migrations a name; in this case we are calling the migration ‘AddUrl’. The scaffolded code is saying that we need to add a Url column, that can hold string data, to the dbo.Blogs table. If needed, we could edit the scaffolded code but that’s not required in this case.
Run the Update-Database command in Package Manager Console. This command will apply any pending migrations to the database. Our InitialCreate migration has already been applied so migrations will just apply our new AddUrl migration. Tip: You can use the –Verbose switch when calling Update-Database to see the SQL that is being executed against the database.
Dealing with Model Changes

RenameColumn during db migration in Entity Framework

I noticed strange thing with db migration that I couldn't fix.
Please help.
I have a class
public class Subscription : BaseEntity
{
...
[Index("IX_Subscription_Status", IsUnique = false)]
public int? Status { get; set; }
...
}
I renamed property Status to BeforeStatus and ran Add-Migration command in Visual Studio.
It generates:
DropIndex(...IX_Subscription_Status...);
DropColumn(... Status ...);
AddColumn(... BeforeStatus ...);
CreateIndex(...IX_Subscription_BeforeStatus...);
I didn't want to drop column, so I changed migration script to
DropIndex(...IX_Subscription_Status...);
RenameColumn(...,Status,BeforeStatus)
CreateIndex(...IX_Subscription_BeforeStatus...);
and ran Update-Database migration. It passed without errors and changed the database.
I added a new property AfterStatus to the class
[Index("IX_Subscription_AfterStatus", IsUnique = false)]
public int? AfterStatus { get; set; }
and ran Add-Migration command. It generates:
AddColumn(... AfterStatus ...);
CreateIndex(...IX_Subscription_AfterStatus...);
I ran Update-Database migration and it passed without errors and changed the database.
So from my point of view, everything is correct and db corresponds c# code. I checked __MigrationHistory table, it contains all latest migrations.
BUT, when I run code, it fails with a DbContext error:
The model backing the 'MyContext' context has changed since the database was created. Consider using Code First Migrations to update the database
If I run Add-Migration command again, it generates:
DropIndex(...IX_Subscription_Status...);
DropColumn(... Status ...);
AddColumn(... BeforeStatus...);
CreateIndex(...IX_Subscription_BeforeStatus...);
AddColumn(... AfterStatus...);
CreateIndex(...IX_Subscription_AfterStatus...);
Why? Why does it generate migration script? Is this error related to RenameColumn operation? Maybe it is because of manually changes of migration script?
Please, does anybody know how to make Entity Framework understand that I have already updated the database?

is it possible to use sql files as EF database migrations?

I'm using EF6.0 and implementing my db with SQLServerDatabaseProject.
I want to use the EF Migration tools for Database migration. but since I have my database on DbProject I want all my migration files to be SQLFiles (not c#)
So I would like to know if EF supports this feature and if not, is it possible to write a new Migration class which keeps the EF features but works this way?
Please also consider that I don't want EF to generate my migrations but I would like to be able to use other migration commands such as update-database and ...
==MORE DETAILS ABOUT THE QUESTION==
I don't want to have c# classes load my sql files. The sql files must be saved for up and down migrations directly and be treated exactly as if they are the DbMigration classes.
A simple example of Migrations dir would be something like this:
Migrations
-> up
-> 201510060807125_alter-course-change-family.sql
-> 201510060813136_alter-course-add-mark-column.sql
-> down
-> 201510060807125_alter-course-change-family.sql
-> 201510060813136_alter-course-add-mark-column.sql
Simply in the migration class use SqlFile extension method:
public partial class MyFancyMigration : DbMigration
{
public override void Up()
{
SqlFile("myUpSQLFile.sql");
}
public override void Down()
{
SqlFile("myDownSQLFile.sql");
}
}
Although you can use SqlFile method, I suggest you to write this on Seed method of your Configuration.cs file in your migration folder.
internal sealed class Configuration : DbMigrationConfiguration<YourDbContext>
{
protected override void Seed(YourDbContext context)
{
base.Seed(context);
context.Database.ExecuteSqlCommand(FileReadAllText("migration.sql"));
}
}
If you write migrations in Up method. It will be executed per each migration when you update the database, which I think you don't expect.
What you want is that your scripts run per each Update-Database. (Not per each migration in it)

Entity code first migrations and deleting databases

We're using EF Code First and migrations for a project. We're commiting our migrations to source, and everything is great. However, if someone delete's their database, or we get a new person on the project, the database will throw errors because it's trying to run the migrations. Is there a way to make it so that if the database doesn't exist, it ignores migrations? I can't seem to find anything about this.
I would look at how you are using DbMigrationsConfiguration from the Entity framework. You might need something like this in your global asx file:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<YourContext, YourConfiguration>());
Then in your configuration file for migrations you may need something like this:
internal sealed class YourConfiguration : DbMigrationsConfiguration<YourContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}...
Without more info and code examples, I can only point you in the right direction.

How to force a new empty EF Migration?

Ok, so I'm relying completely on my migrations and seed code to maintain all database structure and initial data. Because of that, I'm facing a situation where all the changes I'm doing at this version are made directly on the database (Stored Procs and Updates) and nothing has changed on the C# code itself.
The question is: Since I want to do those DataBase specific changes using a new migration (and an "add-migration" will do nothing - cause the code hasn't change), how can I force a new empty code first migration to put my changes manually on it?
In the package manager console issue the command
Add-Migration "My new empty migration"
This will generate this migration template
public partial class Mynewemptymigration : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
You can then create your own custom up and down migration steps. If you model is not up to date there will be migration code in the up and down. In that case you'll have to get your model up to date and then add a new empty migration.
You have to add an empty migration and add the code to the Up and Down method manually. I have found that people tend to think that the code for those methods have to be generated by the tool similar to ".designer" files and this is not the case. In fact more often than not i have found my self editing and adding code there.
For this purpose I place all the sql code that i have to execute in scripts files and the execute then in the Up methods like this:
public override void Up(){
var dirBase = AppDomain.CurrentDomain.BaseDirectory.Replace(#"\bin",string.Empty) + #"\Migrations\SqlScripts";
Sql(File.ReadAllText(dirBase + #"\CreateMyViews.sql"));
Sql(File.ReadAllText(dirBase + #"\CreateMySproc.sql"));
}
public override void Down(){
var dirBase = AppDomain.CurrentDomain.BaseDirectory.Replace(#"\bin",string.Empty) + #"\Migrations\SqlScripts";
Sql(File.ReadAllText(dirBase + #"\DropMySproc.sql"));
Sql(File.ReadAllText(dirBase + #"\DropMyViews.sql"));
}
I recomend you read this link:
http://elegantcode.com/2012/04/12/entity-framework-migrations-tips/
This is a more up-to-date answer...
In Package Manager Console in Visual Studio, add an empty migration targeting your Database context.
add-migration SeedingFacilityTable -context YourDbContextName
It'll create an empty migration provided you don't have any other DB changes to be applied.
Inside the Up method, write the following:
public partial class SeedingFacilityTable : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql(#"Put as many SQL commands as you want here");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
Then run the following command:
update-database -context YourDbContextName
Add-migration actually do exactly what's asked for.
You can just run dotnet ef migrations add or Add-Migration in the package manager console (as mentioned by David) to generate a class with empty Up and Down methods. Then just put your changes inside that class as usual.

Categories

Resources