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?
Related
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
The following used to work. I am unsure what has changed.
var db = new MyDbContext()
var compatible = db.Database.CompatibleWithModel(true)
gives the following error
Model compatibility cannot be checked because the database does not
contain model metadata. Model compatibility can only be checked for
databases created using Code First or Code First Migrations.
I have been able to create and run the migrations using Package Manager and I can see the code in the Migrations folder.
I can see the migrations in the __MigrationHistory table.
I resolved the issue in a different database when the user did not have access to the table. However in this case the user does have access.
The table shows the product version is 6.4.4
I tried creating a new migration to see if there were any differences, but it was empty.
I looked at the configuration.cs in the migrations folder
internal sealed class Configuration : DbMigrationsConfiguration<MigrationDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
}
Then I corrected the type
var db = new MigrationDbContext()
Then I changed the
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()
{
}
}
I have a database with several tables in AZURE SQL Server.
I want to add a new column to one of the tables, but I want to keep all the content of the tables including the table with the new column; hence I don't want to use the
Database.SetInitializer<MyDbContext>(new DropCreateDatabaseIfModelChanges<MyDbContext>());
My code looks like this:
public class DBTables : DbContext
{
public DBTables() : base(ProductKeys.GetDbKey())
{
}
public DbSet<ElementsForPointTable> ElementsForPointTable { get; set; }
public DbSet<StationsDetailsTable> StationsDetailsTable { get; set; }
}
How do I do it?
You could use migrations to update the database scheme.
Open Package Manager Console (Tools -> Library Package Manager -> Package Manager Console)
Run Enable-Migrations command
Change your model
Run Add-Migration command in Package Manager Console.
Run Update-Database command to apply your model changes to the database.
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.