Update database from CodeFirst in EF6 without wiping out data - c#

I want to use Code First Technique of EF6 but when i made changes to table, it drops the database and recreates it, wiping out all data.
Is there any way to stop this from happening?
My Code :
Database.SetInitializer<EmployeeDb>(new DropCreateDatabaseIfModelChanges<EmployeeDb>());

These are the strategies for database initilization in code first approach:
CreateDatabaseIfNotExists: This is default initializer. As the name suggests, it will create the database if none exists as per the configuration. However, if you change the model class and then run the application with this initializer, then it will throw an exception.
DropCreateDatabaseIfModelChanges: This initializer drops an existing database and creates a new database, if your model classes (entity classes) have been changed. So you don't have to worry about maintaining your database schema, when your model classes change.
DropCreateDatabaseAlways: As the name suggests, this initializer drops an existing database every time you run the application, irrespective of whether your model classes have changed or not. This will be useful, when you want fresh database, every time you run the application, like while you are developing the application.
Custom DB Initializer: You can also create your own custom initializer, if any of the above doesn't satisfy your requirements or you want to do some other process that initializes the database using the above initializer.
Here, it can give you general idea and how to use one of these approaches.
Due to your comments CreateDatabaseIfNotExists helps you. With this approach when you add or remove your model classes, your db will be updated and your data will be stable.
Here you can find examples both Context constructor and config file
Another topic about this on stackoverflow.

Related

How to check automatically that I didn't forget to add ef core code first migration

We are using Entity Framework Core 2.2 with code first. Sometimes I change one of the entities, but forget to create a new migration, or I create a migration but only in one context (we have for different db engines). I want to check it automatically (ideally as NUnit test) so it runs in our CI server for every commit.
Manually I would try to create a new migration and check that created Up() and Down() methods are empty. It there any way to do it as a NUnit test?
Where is difficulty in creating a test that :
Creates a new DB
Applies all current migrations to create a schema
Tries to use all the entities. It can be as simple as adding an entity, querying that entity and deep-comparing they are the same.
Drops the DB
If the schema doesn't have a migration for new entity or change in entity, you are sure to get and SQL error out of this.
Sure, every time you create a new entity, you would need to add a new test. But that should be already happening if you are using TDD.
And speed shouldn't be a problem either, as creating and dropping a DB shouldn't take more than few seconds and there won't be many of these kind of tests. And they can be parallelized.
If you want to get fancy and don't want to write test for each entity, it could be possible to do something like this :
Use reflection to get all entity types supported by a Context.
Use auto data generator like Bogus or AutoFixture to fill the entities with data.
Round-trip the entities through DB.
Compare the original with retrieved using deep-comparer like Compare-Net-Objects.
The usefulness of such automated approach would depend on complexity of your data model. Would just work for simple model. But would require lots of tweaking and overrides if the model is complex.

Database Initialization in Entity Framework Code First

I'm learning about EF Code First. I've read Database Initialization Strategies in Code-First and Understanding Database Initializers in Entity Framework Code First articles.
But I'm still confused, where should be the data before initialization? Those articles didn't mention about that and I think it's pretty important.
I'm building a football application, so while initializing app I'd like to insert every team and player name into database (every in the Europe from best leagues - so quite a lot of data). They will not change. Should they be hard-coded in sourcecode? or attached in xml? simple file?
Right now I have: before running, there is initialization prompt (Please wait, initialization...) I read the file, line by line inserting them into database. Is it good way?
It depends on where you are in the development process. You can use a Seed() method on the initializer which runs when the database is created. So if you have a ton of data and will be frequently changing your models with a DropCreate_____ type of initializer - I would recommend just seeding a small amount of data to test with.
When you are happy with your initial design, you can do a full Seed() and switch to database migrations to handle your model changes. This will keep your existing data and has it's own Seed() method for new data.
As to where to get the data, you can look at something like this where you could fetch from a web service or download into csv, xml, etc. http://www.jokecamp.com/blog/guide-to-football-and-soccer-data-and-apis/#footballdata or here http://openfootball.github.io/

Do I need a migration for EF code first when the database does not exist in SQL Azure?

I have tried lots of variations of EF migration v6.0.1 (from no database, to empty databases to existing databases) and I have a particular problem with Azure DB instances not being able to correctly be created on first deploy using Octopus deploy.
There are a number of places where this could be going wrong, so I thought I would check some basics of EF Code First migration with you fine people if I may:
If I create a code-first model, and know that the database does not exist in the intended target database server on Azure. With the default of 'CreateDatabaseIfNotExists' approach and with AutomaticMigrations disabled;
If I then call 'migrate.exe' with the assembly containing my DbContext and migration Configuration will I get a new database created with the current state of the model? or will I get a new database with nothing in it? i.e. do I need to explicitly 'add-migration' for the initial state of the model?
I have read in the documentation that the database instance should be created automatically by the migration process, but no one states clearly (at least to me) that this newly created database will be generated with the current model without a formal 'initial state' migration created.
So the question is this: do I need an explicit migration model generated for migrate.exe to work from?
Through whatever means I try, I get a database but the application launches with the unfriendly message "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." Remembering that this is the same application library that just created the database in the first place (from scratch) I fail to understand how this has happened!
I did manually delete the target database a few times via SQL Server management studio, is this bad? Have I removed some vital user account that I need to recover?
Migrations and the Database Initializer CreateDatabaseIfNotExists are not the same.
Migrations uses the Database Initializer MigrateDatabaseToLatestVersion, which relies upon a special table in the database _MigrationsHistory.
By contrast, CreateDatabaseIfNotExists is one of the Database Initializers which relies upon the special database table EdmMetadata. It does exactly as it implies: Creates a database with tables matching the current state of the model, i.e. a table for each DbSet<T>, only when the database does not exist.
The specific error you have quoted here, Model compatibility cannot be checked because the database does not contain model metadata., occurs due to the existence of DbSet<T> objects which were added to the code base after the initial database creation, and do not exist in EdmMetadata.
There are 4 basic Database Initializers available, 3 of which are for use when migrations is not being used:
CreateDatabaseIfNotExists
DropCreateDatabaseWhenModelChanges
DropCreateDatabaseAlways
Also note, the 4th Initializer, MigrateDatabaseToLatestVersion, will allow you to use Migrations even if AutomaticMigrations is disabled; AutomaticMigrations serves a diffierent purpose, and does not interact with the Database Initializers directly.
If you intend to use Migrations, you should change the Database Initializer to MigrateDatabaseToLatestVersion and forget about the other 3. If, instead, you intend to not use Migrations, then the choice of Initializer is situational.
CreateDatabaseIfNotExists will be more appropriate when you are certain that your data model is not undergoing active change, and you only intend to be concerned with database creation on a new deployment. This Initializer will elp ensure that you do not have any issues with accidental deletion of a database or live data.
DropCreateDatabaseWhenModelChanges is most appropriate in development, when you are changing the model fairly often, and want to be able to verify these changes to the model. It would not be appropriate for a production server, as changes to the model could inadvertently cause the database to be recreated.
DropCreateDatabaseAlways is only appropriate in testing, where your database is created from scratch every time you run your tests.
Migrations differs from these 3 Database Initializers, in that it never drops the database, it instead uses Data Motion to execute a series of Create Table and Drop Table SQL calls.
You also can use Update-Database -Script -SourceMigration:0 in the Package Manager Console at any time, no matter which Database Initializer you are using, to generate a full SQL script that can be run against a server to recreate the database.
Firstly, many thanks to Claies who helped me get to the bottom of this problem. I have accepted his answer as correct as ultimately it was a combination of his response and a few additional bits of reading that got me to my solution.
In answer to the actual posts question 'Do I need a migration for EF code first when the database does not exist in SQL Azure?' the answer is yes you do if you have disabled automatic migrations. But there is a little more to be aware of:
The Azure aspects of this particular problem are actually irrelevant in my situation. My problem was two-fold:
The migration being generated was out of sync with respect to the target model. What do I mean? I mean, that I was generating the migration script from my local database which itself was not in sync with the local codebase which created a migration that was incorrect. This can be seen by comparing the first few lines of the Model text in the __MigrationHistory. This awareness was helped by referring to this helpful post which explains how it works.
And more embarrassingly (I'm sure we've all done it) is that my octopus deployment of the web site itself (using Octopack) somehow neglected to include the Web.Config file. From what I can tell, this may have occurred after I installed a transform extension to Visual Studio. Within my nuget package I can see that there is a web.config.transform file but not a web.config. Basically this meant that when the application started up, it had no configuration file to turn to, no connections string at all. But this resulted in the slightly misleading error
Model compatibility cannot be checked because the database does not
contain model metadata.
Whereas what it should have said was, there isn't a connection string you idiot.
Hopefully this helps people understand the process a little better after reading Claies answer and also that blog-post. First though, check you have a web.config file and that it has a connection string in it...

Entity Framework/External synchronisation architecture

I have an application which queries a local store of data (currently backed by an XML file), using Linq to Objects. Periodically, another thread in the application will query a remote server for updated data, and if it exists, will download all of the remote data, deserialise it and replace the local objects with newly deserialised ones before saving the new XML to disk.
I have decided to replace the XML file with a SQLite database, and I intend to use Entity Framework to interact with it. This has prompted me to re-look at the way external changes are applied, and I've decided that only data where the remote entities updated_at property is newer than the local entity will be updated (rather than the current approach of replacing the whole data set)
So I must write a method to download the external changes and update or insert the relevant entities into the SQLite database.
What I don't understand is where, in architectural terms, this method should sit. My (potentially naive) thinking is that a generic UpdateFromRemoteObjects<T>(List<T> updatedItems) method could sit in the DbContext class, and would accept a list of entities and update the appropriate DbSet. But this feels like it may be too closely coupled to the DbContext. Should I use a repository to provide a layer to implement this? Or is another application architecture more appropriate?
Many people start with CRC when designing components: Classes have Responsibilities and Collaborators
First consider the single responsibility principle: a class with two or more responsibilities is probably doing too much. This is your reason for not putting the method on the DbContext: this updating stuff is a new distinct responsibility, so create a class for it.
I can see this class doing 2 things: QueryRemoteServerForChanges and UpdateLocalObjects.
Now consider its Collaborators. it seems to need two: an instance of DbContext for the local changes, and a instance of whatever gives access to the remote data.
So not a repository no; and not a layer; but definitely a class with a responsibility.

Code first database migration

We are using the Code-first approach without an Edmx file, its running fine to create database the first time.
But if I am adding new data entities say new class to my database context then it is not able to add that to new table in that database.
Say for example there are two table initially in database.
ex Database : DbTest
Table : Tbl1, Tbl2
Now if I add new table, say class name 'Tbl3', then it should be adding it into the existing database.
Can any one please explain to me with an example how it can be achieved via code first approach?
I have seen mentioned something like Database.SetInitializer(new ........)
What do I need to put in the blank area of the constructor above?
If you look in your database you will see a table called "EdmMetadata" which Entity Framework uses to determine if any changes have been made to your model since the database was created (which it has in your case).
The default behaviour is for an exception to be thrown if the model and database differ. To get different behaviour you will need to use an IDatabaseInitializer<TContext>.
Luckily, Entity Framework ships with some default implementations of this interface:
CreateDatabaseIfNotExists<TContext> - This will create the database if one doesn't already exist.
DropCreateDatabaseAlways<TContext> - This will re-create the database each time your application is run.
DropCreateDatabaseIfModelChanges<TContext> - This will re-create the database if a change is detected in the EdmMetadata table (usually as a result of creating new tables).
You can of course also create your own implementation of this interface by overriding the InitializeDatabase method.
an example of using one of these initialization strategies is shown below:
Database.SetInitializer(
new DropCreateDatabaseIfModelChanges<NameOfYourDbContextClass>())
Think carefully before choosing an initialization strategy as you could end up losing data already entered into the database and this may not be what you want.
The implementations provided by Entity Framework provide a Seed method for loading your database with data so that you can preload your database with default data each time it is created.
This article provides further information.

Categories

Resources