Entity Framework CodeFirst Initial Migration of Existing Database - entity-framework-6

I have an existing database with data. I want to add code-first, non-automatic data migrations to the project.
My question is for the initial migration, should the initial migration be a snapshot of the current database schema or should it have empty Up() and Down() methods, essentially starting the migrations with the first schema change, when it occurs?
I can see the value in having the 1st migration being a snapshot of the existing schema. Just curious.
This?
PM> Add-Migration InitialMigration -IgnoreChanges
Or this?
PM> Add-Migration InitialMigration

I use Add-Migration InitialMigration and Up() contains all the CreateTable etc calls required to set up the initial database. Seed() menthos in the Configuration class adds any data required.

Related

Why Migration.BuildTargetModel has so much duplicate code?

I'm setting up EF Core 3.1.3 migrations against an existing SQL Server database.
This is what I've done so far:
Scaffold my model from the existing database.
Add the InitialCreate migration.
Remove the contents of the Up() method in InitialCreate.
Update database to create the __EFMigrationsHistory table.
Then I added a property to an entity class and ran dotnet ef add migration.
Now looking at the BuildTargetModel method of the second migration I see that it contains pretty much the same code as MyDbContextModelSnapshot.BuildModel. I.e. it lists all entities and all their properties and relationships.
What does BuildTargetModel on a migration do? Why does it have to duplicate most of the snapshot code? I would only expect to find the diff in a migration.
As confirmed by the developers of EF Core, this behaviour is by design:
https://github.com/dotnet/EntityFramework.Docs/issues/2288

Unable to update database to match the current model because there are pending changes and automatic migration is disabled

I, for the life of me, can't get rid of this error message. I have tried almost everything that I can.
MyDBContext.cs
public MyDBContext() : base("ConnStr_Dev")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDBContext, DbMigrationsConfiguration<MyDBContext>>());
//Database.SetInitializer<MyDBContext>(null);
base.OnModelCreating(modelBuilder);
}
GenericRepository.cs
public void Insert(T obj)
{
table.Add(obj); //this is where it throws the error, inserting first time.
}
Tried all of these in different combinations
Enable-Migrations -EnableAutomaticMigrations -Force
Add-migration Initial -IgnoreChanges
Update-Database
I have tried deleting the Migrations table, deleting the entire database, everything.
Any Migrations experts please?
Edit: the DAL contains the GenericRepository and the context class.
I fought with this error too. I added the migration and then made what I thought was a trivial change.
This property: IMigrationMetadata.Target in your migration isn't random. It's computed based on the state of the model at the time the migration was completed. (That may be an oversimplification.)
So if you make additional changes, it looks as there are additional pending changes that require yet another migration.
In my case, because the changes hadn't been committed to source control, the fix was to delete and re-add the migration. It took a while to figure out the cause because the error message is unclear unless you already know what's causing it. But the lesson I learned (being relatively new to EF) is that changes to the models require either a new migration or re-doing the migration that I'm working on.
Delete your Migrations folder from your solution
Delete the dbo.__MigrationHistory table from your database
Open Package Manager Console and Enable-Migrations
Add your initial migration Add-Migration Initial
Update-Database
Done
You simply made changes to one or more of your entity classes. Whether you added a new property, changed the data type of that particular property or you simply added a new entity class, in all of those cases you indeed need to add a new migration.
Seeing that you've already tried that, make sure that when you execute the Add-Migration command in Package Manager Console that you've selected the project that contains your DBContext class, the Configuration class and Migrations folder. Furthermore, you are passing a specific connection string to the base class (DbContext) of the MyDBContext class. Make sure you are also upgrading and updating the correct database.
Know that you can perform an Add-Migration command and an Update command to a specific database:
Example snippets:
Add-Migration AddProperty1 -ConnectionString "Data Source=.\SQLEXPRESS;Initial Catalog=MyDatabaseCatablog;Connect Timeout=30;User ID=MyUser;Password=mypassword12345" -ConnectionProviderName "System.Data.SqlClient" -Verbose
and
Update-Database -ConnectionString "Data Source=.\SQLEXPRESS;Initial Catalog=MyDatabaseCatablog;Connect Timeout=30;User ID=MyUser;Password=mypassword12345" -ConnectionProviderName "System.Data.SqlClient" -Verbose
Hope this helps.
In my case the error was resolved by adding a DatabaseInitializerForType... appSetting.
<appSettings>
<add key="DatabaseInitializerForType EasyEntity.EasyContext, EasyEntity" value="EasyEntity.EasyInitializer, EasyEntity" />
This error is weird enough in my case, I forgot to uncomment the CONNECTIONSTRING setting, means having a proper connectionstring resolved this error. Hope it helps!

Why Code-First Migration not worked Correctly?

I Use code-first migration but I has error when run application.
error:Cannot find the object "dbo.Products" because it does not exist or you do not have permissions.
I have already got deleted Products table manually on sql server.I expect when Re-Run Project All table recreate if not exist in sql server.
In addition,I write 2 line for configure migration.
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
any help ?
If you are using migrations you shouldn't "manually" change the database. So now EF is generating code to remove the table for you, but it doesn't exist. Solution is to comment out the code in the Up() method that removes the table and update-database. See https://msdn.microsoft.com/en-US/data/dn481501
If you want your database recreated, you will need to switch to an initializer such as DropCreateDatabaseIfModelChanges. See http://www.entityframeworktutorial.net/code-first/database-initialization-strategy-in-code-first.aspx.

Why Code First Migration No Update Table that Exist In DataBase?

I want Update database by code first migration .for example I have 3 entity in contex and 1 table in database and there is a problem when I run program and get this error:There is already table.
Migration Configuration
internal sealed class Configuration : DbMigrationsConfiguration<ApplicationDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
// AutomaticMigrationDataLossAllowed = false;
}
protected override void Seed(ApplicationDbContext context)
{
// This method will be called after migrating to the latest version.
}
}
IdentityModel
public ApplicationDbContext() : base("DefaultConnection" )
{
Database.SetInitializer<ApplicationDbContext>(new MigrateDatabaseToLatestVersion<ApplicationDbContext, Migrations.Configuration>());
}
any help ?
Have you tried to use the Add-Migration "migration_name" before calling update database? Or maybe try to use Update-Database -Force.
Otherwise, I have found some steps that maybe could be useful:
Remove the existing Migrations folder in your project, and DROP the table __MigrationHistory from the existing database.
Run the enable-migrations command from the Package Manager Console.
Run the add-migration command to create an initial migration.
Remove all of the code in Up() method for the initial migration.
Run the update-database command to apply the initial migration to your database. This doesn't make any changes to existing objects (because the Up() method contains no code), but it marks the existing database as having been migrated to the initial state.
Make changes to your code-first model.
Run the add-migration command to create a new migration. The code in the Up() method of the new migration will contain only the changes to your object model.
Run the update-database command to apply the changes to your database.
That's a common problem with migrations. When you add a new migration it compares the current code model to the prior code model stored in the prior migration. If this is the first migration it will thus generate code for everything, so sometimes the code will try to add objects that already exist.
To get past this, you can comment out the code in the Up() method of the migration for the items that already exist and then apply the migration (update-database). Now it will correctly generate just the changes moving forward.
To prevent this, you should always generate an initial snapshot of your database without generating any changes:
add-migration MyStartingPoint -IgnoreChanges // ignorechanges flag tells EF to just take snapshot with no code in Up()
Here is a document on how migrations operate "under the hood".

Insert InitialCreate migration into database without performing the schema changes

I am adding Code First migrations to an existing Entity Framework 6 domain with existing databases. I need the following behaviour:
If the database exists, insert the InitialCreate migration but do not perform the contents of the migration Up().
If the database does not exist, create it and run the contents of Up() and Down() to create an empty but correct-schema database.
I need (1) for when I release through the Continuous Delivery deployment. I need (2) for when a developer is cleaning down their machine and starting fresh. I do not want to use automatic migrations.
I appreciate that a Migration has no concept of the Database Context, it's only responsible for generating a series of SQL instructions.
Are these my only options?
1. Move contents of Up and Down out of InitialCreate and into Configuration.Seed
The InitialCreate migration runs Up() but no changes are made. In Seed() we have access to DbContext, so we can work out if the tables exist and create them if needed.
I think this might break when there are lots of migrations to run as Seed() is called after the migrations. On an empty database, the creation of the tables would be happening after updates to those schemas.
2. Perform the Up() method as a SQL Script
Migrations allows the developer to put inline SQL into Up() and Down(). Move the creation of the database into inline SQL and add a IF NOT EXISTS at the top.
I don't like this because you lose the use of the model that is supplied with the InitialCreate. If the model is updated, the fixed SQL string won't.
3. Empty out the Up() and Down() methods, do a release, put the creation code back in, do another release
When the InitialCreate migration is run first time, it won't have anything in it. The entry will go into the migrations database without running anything.
Once that first release has been performed, I can then put the creation code back in so that when future developers run it without a database, it will create properly.
Note: This one is my current favourite as it uses Entity Framework as designed and I can personally control adding the code back in after a release.
Is there a better way?
Edit
I am unable to build the database from empty, this might be something to do with the Context model creation. It uses a bespoke pluggable method:
public MyObjectContext()
{
((IObjectContextAdapter) this).ObjectContext.ContextOptions.LazyLoadingEnabled = true;
((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 180;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
System.Type configType = typeof(AnswerMap); //any of your configuration classes here
var typesToRegister = Assembly.GetAssembly(configType).GetTypes()
.Where(type => !String.IsNullOrEmpty(type.Namespace))
.Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
foreach (var type in typesToRegister)
{
dynamic configurationInstance = Activator.CreateInstance(type);
modelBuilder.Configurations.Add(configurationInstance);
}
base.OnModelCreating(modelBuilder);
}
All the map objects are in the same DLL, the domain entities used for the database tables are in a separate DLL.
This is what we do:
1) Create an initial migration that is a snapshot of the current database. Use -IgnoreChanges to keep any code out of the Up(). You don't need the Up() code because EF will compare the prior model (blank) to the one stored in the migration and realize you need to add all the existing objects at the time of the snapshot.
add-migration Initial -IgnoreChanges
2) Add new migrations as you develop. In a team environment you could run into the issues outlined here: https://msdn.microsoft.com/en-US/data/dn481501
3) You can generate an idempotent script that will rebuild an entire system from scratch and apply any (or all) migrations.
Update-Database -Script -SourceMigration $InitialDatabase
https://msdn.microsoft.com/en-us/data/jj591621.aspx?f=255&MSPPError=-2147217396#idempotent

Resources