Update existing database using entityframework - identityserver4

We are upgrading our installation of IdentityServer4 from 2.1.1 to 2.5.4 but are unsure on the best approach to update the existing database.
We have updated the nuget packages from 2.1.1 to 2.5.4
- IdentityServer4.EntityFramework
- IdentityServer4.AsNetIdentity
We tried to add-migrations and generate the sql scripts
dotnet ef migrations script -c configurationdbcontext -i -o confcontxt.sql
But it appears that the model changes does not result in the necessary sql (AlterTable ....)
What are we missing ?

Strange but apparently deleting the _EFMigrationsHistory did the trick. Read EF migration shows empty Up() Down() methods, no tables created in database or/and
EF migration shows empty Up() Down() methods
All the basic EntityFramework stuff is well documented here: https://www.learnentityframeworkcore.com/migrations

Related

Problem with deleting a migration in SQL Server (connected with Visual Studio 2022) [duplicate]

I'm using EF 6.0 for my project in C# with manual migrations and updates. I have about 5 migrations on the database, but I realised that the last migration was bad and I don't want it. I know that I can rollback to a previous migration, but when I add a new (fixed) migration and run Update-Database, even the bad migration is applied.
I was trying to rollback to the previous migration and delete the file with bad migration. But then, when I try to add new migration, I get error when updating database, because the migration file is corrupted (more specifically, first line of code rename the table A to B and is next lines, EF is trying to update table with name A - maybe it is some EF bug).
Is there some query I can run, which would tell EF something like "Forget last migration like it never existed, it was bad"? Something like Remove-Migration.
Edit1
I found solution suited for me. Changing model to the good state and run Add-Migration TheBadMigration -Force. This will re-scaffold the last, not applied migration.
Anyway, this still not answer the original question completely. If I UpdateDatabase to the bad migration, I did not found good way how to rollback and create new migration, excluding the bad one.
Thanks
You have 2 options:
You can take the Down from the bad migration and put it in a new migration (you will also need to make the subsequent changes to the model). This is effectively rolling up to a better version.
I use this option on things that have gone to multiple environments.
The other option is to actually run Update-Database –TargetMigration: TheLastGoodMigration against your deployed database and then delete the migration from your solution. This is kinda the hulk smash alternative and requires this to be performed against any database deployed with the bad version.
Note: to rescaffold the migration you can use Add-Migration [existingname] -Force. This will however overwrite your existing migration, so be sure to do this only if you have removed the existing migration from the database. This does the same thing as deleting the existing migration file and running add-migration
I use this option while developing.
As the question indicates this applies to a migration in a development type environment that has not yet been released.
This issue can be solved in these steps:
Restore your database to the last good migration.
Delete the bad migration from your Entity Framework project.
Generate a new migration and apply it to the database.
Note: Entity Framework and Entity Framework Core use slightly different command names
Step 1: Restore to a previous migration
If you haven't yet applied your migration you can skip this part. To restore your database schema to a previous point issue the Update-Database command with -TargetMigration option to specify the last good migration. For EFCore use Update-Database "Name-of-Migration"
If your entity framework code resides in a different project in your solution, you may need to use the '-Project' option or switch the default project in the package manager console.
Update-Database –TargetMigration: <name of last good migration>
For EFCore:
Update-Database <name of last good migration>
To get the name of the last good migration use the 'Get-Migrations' command to retrieve a list of the migration names that have been applied to your database, use 'Get-Migration' without the 's' if you are using EFCore.
PM> Get-Migrations
Retrieving migrations that have been applied to the target database.
201508242303096_Bad_Migration
201508211842590_The_Migration_applied_before_it
201508211440252_And_another
This list shows the most recent applied migrations first. Pick the migration that occurs in the list after the one you want to downgrade to, ie the one applied before the one you want to downgrade. Now issue an Update-Database.
Update-Database –TargetMigration: "<the migration applied before it>"
For EFCore:
Update-Database "<the migration applied before it>"
All migrations applied after the one specified will be down-graded in order starting with the latest migration applied first.
EF will reject the command if your downgrade might cause data loss. Use the '-Force' option to accept the data loss and allow the command to execute.
Step 2: Delete your migration from the project
If you are using Entity Framework Core you can use the 'remove-migration' command, for Entity Framework, delete the files of the unwanted migration in your EF project 'Migrations' folder manually. At this point, you are free to create a new migration and apply it to the database.
For EFCore:
remove-migration name_of_bad_migration
Step 3: Add your new migration
add-migration my_new_migration
Step 4: Apply your migration to the database
update-database
For those using EF Core with ASP.NET Core v1.0.0 I had a similar problem and used the following commands to correct it (#DavidSopko's post pointed me in the right direction, but the details are slightly different for EF Core):
Update-Database <Name of last good migration>
Remove-Migration
For example, in my current development the command became
PM> Update-Database CreateInitialDatabase
Done.
PM> Remove-Migration
Done.
PM>
The Remove-Migration will remove the last migration you applied. If you have a more complex scenario with multiple migrations to remove (I only had 2, the initial and the bad one), I suggest you test the steps in a dummy project.
There doesn't currently appear to be a Get-Migrations command in EF Core (v1.0.0) so you must look in your migrations folder and be familiar with what you have done. However, there is a nice help command:
PM> get-help entityframework
Refreshing dastabase in VS2015 SQL Server Object Explorer, all of my data was preserved and the migration that I wanted to revert was gone :)
Initially I tried Remove-Migration by itself and found the error command confusing:
System.InvalidOperationException: The migration '...' has already been
applied to the database. Unapply it and try again. If the migration
has been applied to other databases, consider reverting its changes
using a new migration.
There are already suggestions on improving this wording, but I'd like the error to say something like this:
Run Update-Database (last good migration name) to revert the database schema back to to that state. This command will
unapply all migrations that occurred after the migration specified to
Update-Database. You may then run Remove-Migration (migration name to remove)
Output from the EF Core help command follows:
PM> get-help entityframework
_/\__
---==/ \\
___ ___ |. \|\
| __|| __| | ) \\\
| _| | _| \_/ | //|\\
|___||_| / \\\/\\
TOPIC
about_EntityFrameworkCore
SHORT DESCRIPTION
Provides information about Entity Framework Core commands.
LONG DESCRIPTION
This topic describes the Entity Framework Core commands. See https://docs.efproject.net for information on Entity Framework Core.
The following Entity Framework cmdlets are included.
Cmdlet Description
-------------------------- ---------------------------------------------------
Add-Migration Adds a new migration.
Remove-Migration Removes the last migration.
Scaffold-DbContext Scaffolds a DbContext and entity type classes for a specified database.
Script-Migration Generates a SQL script from migrations.
Update-Database Updates the database to a specified migration.
Use-DbContext Sets the default DbContext to use.
SEE ALSO
Add-Migration
Remove-Migration
Scaffold-DbContext
Script-Migration
Update-Database
Use-DbContext
You can also use
Remove-Migration -Force
This will revert and remove the last applied migration
I am using EF Core with ASP.NET Core V2.2.6. #Richard Logwood's answer was great and it solved my problem, but I needed a different syntax.
So, For those using EF Core with ASP.NET Core V2.2.6 +...
instead of
Update-Database <Name of last good migration>
I had to use:
dotnet ef database update <Name of last good migration>
And instead of
Remove-Migration
I had to use:
dotnet ef migrations remove
For --help i had to use :
dotnet ef migrations --help
Usage: dotnet ef migrations [options] [command]
Options:
-h|--help Show help information
-v|--verbose Show verbose output.
--no-color Don't colorize output.
--prefix-output Prefix output with level.
Commands:
add Adds a new migration.
list Lists available migrations.
remove Removes the last migration.
script Generates a SQL script from migrations.
Use "migrations [command] --help" for more information about a command.
This let me role back to the stage where my DB worked as expected, and start from beginning.
First, Update your last perfect migration via this command :
Update-Database –TargetMigration
Example:
Update-Database -20180906131107_xxxx_xxxx
And, then delete your unused migration manually.
As of .NET Core 2.2, TargetMigration seems to be gone:
get-help Update-Database
NAME
Update-Database
SYNOPSIS
Updates the database to a specified migration.
SYNTAX
Update-Database [[-Migration] <String>] [-Context <String>] [-Project <String>] [-StartupProject <String>] [<CommonParameters>]
DESCRIPTION
Updates the database to a specified migration.
RELATED LINKS
Script-Migration
about_EntityFrameworkCore
REMARKS
To see the examples, type: "get-help Update-Database -examples".
For more information, type: "get-help Update-Database -detailed".
For technical information, type: "get-help Update-Database -full".
For online help, type: "get-help Update-Database -online"
So this works for me now:
Update-Database -Migration 20180906131107_xxxx_xxxx
As well as (no -Migration switch):
Update-Database 20180906131107_xxxx_xxxx
On an added note, you can no longer cleanly delete migration folders without putting your Model Snapshot out of sync. So if you learn this the hard way and wind up with an empty migration where you know there should be changes, you can run (no switches needed for the last migration):
Remove-migration
It will clean up the mess and put you back where you need to be, even though the last migration folder was deleted manually.
For EF 6 here's a one-liner if you're re-scaffolding a lot in development. Just update the vars and then keep using the up arrow in package manager console to rinse and repeat.
$lastGoodTarget = "OldTargetName"; $newTarget = "NewTargetName"; Update-Database -TargetMigration "$lastGoodTarget" -Verbose; Add-Migration "$newTarget" -Verbose -Force
Why is this necessary you ask? Not sure which versions of EF6 this applies but if your new migration target has already been applied then using '-Force' to re-scaffold in Add-Migration will not actually re-scaffold, but instead make a new file (this is a good thing though because you wouldn't want to lose your 'Down'). The above snippet does the 'Down' first if necessary then -Force works properly to re-scaffold.
Be sure you don´t have error in project files, even in your migration files, I had an error in my last migration file and did not allow me remove it.

How can I set a custom name for the EF core migration history table and have it used when generating migration scripts?

I have an ASP.NET Core project which uses EF Core, and migrations have already been run using the default migration history table (dbo.__EFMigrationsHistory). I want to store all migrations in a table with a different name and schema.
In ConfigureServices (within Startup.cs) I have the following code (as per the documentation):
serviceCollection.AddDbContext<DatabaseContext>(
options =>
{
options.UseSqlServer(
connectionString,
x => x.MigrationsHistoryTable("__MigrationHistory", "MySchema"));
});
I have manually created the MySchema.__MigrationHistory table, copied over all the data from dbo.__EFMigrationsHistory, and dropped dbo.__EFMigrationsHistory.
I was expecting this to mean that all future migrations would go into MySchema.__MigrationHistory but when I added a blank migration as a test and ran script-migration -from previousMigrationName (from the Visual Studio package manager console) the SQL it gave me adds the history record to dbo.__EFMigrationsHistory.
What else do I need to do in order to get EF Core to use MySchema.__MigrationHistory for all new migrations?
It turns out that the reason for this problem was that I hadn't understood how EF Core is configured to run migrations when the DbContext is in a different assembly from the ASP.NET Core app.
The ASP.NET Core app has a Startup.cs which I'd modified, but I wasn't aware that the assembly containing the DbContext contained an implementation of IDesignTimeDbContextFactory. In this class there is another call to the UseSqlServer method, and I needed to add the options there too. This is what is actually being used for migrations, as they don't go through the ASP.NET Core app.

ASP.NET Core 3.0 - Can't Update-Database

I just created the project using the command dotnet new angular -o <output_directory_name> -au Individual and scaffold identity then I installed Microsoft.EntityFrameworkCore.SqlServer but when I run the command update-database, I get the error below.
Failed executing DbCommand (4ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE [AspNetRoles] (
[Id] TEXT NOT NULL,
[Name] TEXT(256) NULL,
[NormalizedName] TEXT(256) NULL,
[ConcurrencyStamp] TEXT NULL,
CONSTRAINT [PK_AspNetRoles] PRIMARY KEY ([Id])
);
and then at the end end another error
Error Number:2716,State:1,Class:16
Column, parameter, or variable #2: Cannot specify a column width on data type text.
Below is the generated CreateIdentitySchema migration
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(nullable: false),
Name = table.Column<string>(maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
ApplicationDbContextModelSnapshot.cs
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasColumnType("nvarchar(256)")
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.HasColumnType("nvarchar(256)")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles");
});
How to fix this errors so I can update-database?
Changing 'TEXT' to 'VARCHAR' in 00000000000000_CreateIdentitySchema.Designer.cs resulted in the following error. The same happens when I change it to 'NVARCHAR'
Data type 'VARCHAR' for property 'Id' is not supported in this form. Either specify the length explicitly in the type name, for example as 'NVARCHAR(16)', or remove the data type and use APIs such as HasMaxLength to allow EF choose the data type.
I had this error and it can be fixed as follows.
Open up the project and delete 2 migration files and 1 snapshot file. Most likely named 0000...InitialCreate.cs, 0000...InitialCreate.Designer.cs and the ...DbContextModelSnapshot.cs. Leave the DbContextClass.
Delete the database.
Use dotnet to create a new migration and update the database. I also script the migration to check it.
dotnet ef migrations add InitialCreate --context ApplicationDbContext -v
dotnet ef database update --context ApplicationDbContext -v
dotnet ef migrations script --context ApplicationDbContext -v
These answers were all helpful, especially the one from #klent. I had generated a new project using:
dotnet new angular -o [MY PROJECT] -au Individual
This produced a new project that used Sqlite as the data provider, although I wasn't aware of that. I changed the connection string to my SQL Server, then ran:
dotnet ef database update
and got the error posted in the original question. After reviewing the answers here I realized that I had the incorrect data provider, and the migrations were targeting Sqlite syntax, which was using TEXT(256) for one of the column specifications. So my specific steps to correct were to:
Remove the Microsoft.EntityFrameworkCore.Sqlite Nuget package.
Install the Microsoft.EntityFrameworkCore.SqlServer Nuget package.
In the ConfigureServices method of my Startup.cs, change the services.AddDbContext call to use options.UseSqlServer instead of options.UseSqlite.
Remove the _CreateIdentitySchema and ApplicationDbContentsModelSnapshot classes from the Migrations folder.
After ensuring the connection string in AppSettings.json points to the SQL Server and not Sqlite, run dotnet ef migrations add CreateIdentitySchema -o Data\Migrations. Note that the output folder specified in the -o parameter may be different for you.
Check the Visual Studio Project Explorer. Two new classes should now appear in the Migrations folder.
Run dotnet ef database update. This will create the tables in the database noted in the connection string.
Additionally, if you want your tables to be in a specific schema, for example "Auth", open your ApplicationDbContext class and add:
protected override void OnModelCreating( ModelBuilder builder )
{
base.OnModelCreating( builder );
builder.HasDefaultSchema( "Auth" );
}
However, this will set the schema for all access that uses this DbContext. It wasn't a problem for me since I'm not using EF for my application data, just Identity data. YMMV.
As already answered by a few others the default Identity installation seems to create the wrong column types; namely that some of the Id columns should be varchar and not text.
I had exactly the same issues as you and spent ages trying to effectively solve it.
The quickest way I found to solve it, and for anyone else coming across this problem, is to:
Create the new project
Delete the Migrations folder completely
Install the package for Sql Server (Or whatever data system you're using) and connection string details
Add your own migration using dotnet ef migrations add <MIGRATION NAME> or Add-Migration (this will write new migration designer files from scratch with the correct column structure
Lastly, update your database with dotnet ef database update or Update-Database
As per comments from #sepupic and #PeterSmith, the problem was that the auto-generated code in 00000000000000_CreateIdentitySchema.Designer.cs had TEXT fields with HasMaxLength so I changed it to VARCHAR then I added HasMaxLength(450) to all VARCHAR Ids then I tried to update-database again and it worked.
I run the project and tried to Register a user and I got the error below
System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.Bolean'
Since I still had errors I did the following:
I deleted the generated table then created a new project with the command dotnet new angular -o <output_directory_name> -au Individual
I didn't scaffold new identity to the newly created project
I copied the db name from my previous project and run the command update-database
There were two missing tables DeviceCodes and PersistedGrants so I run the command add-migration but it didn't generate anything so I copied the migration code of the two tables from my previous project and pasted it the empty migration code I created earlier.
I run the project again and register a new user and it finally worked
I still don't know why I got errors since the project I did before didn't have any problem with the auto-generated code.
I had an error like yours as
Column 'Id' in table 'Roles' is of a type that is invalid for use as a key column in an index.
Because I changed the table names those are coming with Individual Identity of Asp.Net Core web application.
To put it simply,
Delete everything in Migrations Folder apart from ApplicationDBContext.
Add-Migration
Make sure if your tables names are matching in Up, Down and BuildTargetModel
Then update-database
It worked for me!
Edit : My main point is that make sure if your tables names are matching in Up, Down and BuildTargetModel. After that update-database will work.
I resolved this database update error with the first answer by #abCsharp, but not until I noticed that the project, which I started with the option of Identity, had created a new migrations folder under the project folder. The original migrations folder was under a Data folder that also contained the ApplicationDbContext.
I deleted the original folder (for cleanliness) and ran the newly created migration which worked. I also deleted the migrations history table in the database, which contains tables for which I am not using migrations.
FWIW All the data types for text in all the tables are nvarchar.

Missing Migration data in SQL when trying to add-migration

I have made use of a backup database and have added a new table using Code First. Now when I tried using add-migration, I got this error:
Unable to generate an explicit migration because the following
explicit migrations are pending
Suggesting that the Migrations in the project do not match which are in the DB, which when I looked, there are NO migrations in the __migration table any more ?
As these tables exist in the DB, how do I get all of these migrations inserted into my SQL DB ? Is there a way I can get them all added, so that the projects migrations and the SQL DB migrations will match, so that I can continue adding/editing tables ?
Thanks in advance for any help.
So I found something that did help! It unfortunately meant that I lost all of my migration files, but thats not the end of the world.
The below is reference from this site: Click here
Remove the _MigrationHistory table from the Database
Remove the individual migration files in your project's Migrations folder
Enable-Migrations in Package Manager Console
Add-migration Initial in PMC
Comment out the code inside of the Up method in the Initial Migration
Update-database in PMC (does nothing but creates Migration Entry)
Remove comments in the Initial method
I hope this helps someone else as well.

Update Database with Migrations CLI on VS for Mac (DotNet Core 2)

I created the Models of my database on VS for Mac and used terminal for create migrations:
dotnet ef migrations add IntitialMigration
Then, I updated my database:
dotnet ef database update
But after I changed my Models and I created another migration:
dotnet ef migrations add SecondMigration
And tried to update the database:
dotnet ef database update SecondMigration
I received the following error:
There is already an object named 'Emails' in the database.
I've searched and I found a probably solution:
Add-Migration SecondMigration -IgnoreChanges
But this only works at PMC on Windows. I'm using VS for Mac and all the commands are typed on Terminal. Does anybody know how to update a database using Migrations after change the Models?
I found the solution. It seems that on VS 2017 for Windows, when you add a Migration, it is automatically added on the solution. But, on VS for Mac, that doesn't happen. You need to manually add the each new migration to the solution. I created the InitialMigration migration and update it to the database. For some reason I don't know why, I removed the migration from the solution and I created the new SecondMigration migration. That's the reason that all the tables that were on InitialMigration were on SecondMigration too.
If you just run update database it will also try to update with previous migration. (which is why its complains about adding whats already there). You can run an update just for one single migration by adding the name of the migration you want to run after the command.

Resources