I have been playing around with EF6 CodeFirst and Migrations. So far all good. But there is one thing I don't understand (conceptually):
In my specific case I am determining the database to connect to at runtime (via some external config XML / JSON or similar). So during development I am a) not certain what database it is I am working with and b) do not necessarily have one available. But EF still requires one, because otherwise I cannot use Update-Database. And if I cannot use Update-Database, I cannot scaffold further migrations.
Is there something I am missing or do I necessarily need a dev-database to develop something using EF6?
The real problem I face is that Update-Database fails with an error telling me that connecting to a DB failed.
Related
I have a webapp uses EF, and a separated EF migration project.
The webapp is deployed and running.
Now I manually run EF migration which alter the db schemas, which make it very different from before.
So what will happen to the running webapp? Does it crash? What is best way to handle this situation?
If you are using Code First (that apparently you are), it will crash with the following error:
The model backing the 'dbContext' context has changed since the
database was created.
Otherwise, depending on the changes you have made (that seem to be a lot) it still has a good chance of crashing.
A safe approach is to first stop the app and then update the database and the app.
I am looking for easy way to reuse edmx file created with EF6 over SQL Server to PostgreSQL
I have used database-first with EF6 on SQL Server and everything worked fine.
We are going to use PostgreSQL.
I have already migrated the database to PostgreSQL, and installed EntityFramework6.Npgsql, and I wanted use database-first approach again.
I tried to update from database but it looks that I have to fix all the edmx file. The original entity model is quite complex, with abstract class, complex types and enum types.
The new edmx file lost inheritance and complex types.
Do you know an easy way to do it?
I don't know if you can get the EDMX file to work with PostgreSQL, but you might be able to use scaffolding and get a db first approach. Something like:
dotnet ef dbcontext scaffold
This would allow you to make changes in the database and have them reflected in code. I'm no PostgreSql expert but this article sure makes it look like it's possible.
If you want a more graphical approach then you may want to consider switching to code first and using the class designer in visual studio.
My team has inherited a database application that contains hundreds of tables. The application uses Entity Framework and takes a database first approach for development. Our current process is to pull a table or two at a time into the edmx using the Update Model From Database... tool.
We are considering making a new API with .Net Core, but as far as I can tell from the research I have done, there is no equivalent process in the Entity Framework Core tools. The closest thing I can find is to reverse engineer the entire database with Scaffold-DbContext, and then use migrations for all future database changes. We can't scaffold the entire database, because some of the tables have errors, and fixing all those errors is not a viable option for us right now.
I have found that I can supply a list of tables that I want scaffolded with the initial Scaffold-DbContext call, but I'm not sure if migrations can be used in a similar way to the Update Model From Database... tool. Can I use migrations to add tables that already exist in our database? If not, what other options should I be looking at?
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...
I'm following the Entity Framework tutorial on:
Link
I've downloaded the source code, and ran. The project works fine (using the default connection string).
<add name="SchoolContext" connectionString="Data Source=|DataDirectory|School.sdf" providerName="System.Data.SqlServerCe.4.0" />
Next i've changed the connection string to connect to a remote server (which successfully connects). However the tables aren't created and when running the application and accessing the controller I get the following error.
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.
My database user is 'dbowner' so I wouldn't imagine it's database access issues.
I'm new to EF, and don't know much about Code First Migrations. Have you come across the above error, and would Code Migrations solve this issue? If so why?
From my reading (please correct me if I am wrong) the scenario here is that you have an existing (perhaps empty) database on a remote server that you wish to put your EF code-first work into.
The error is coming about because, I think, EF is looking for a _MigrationHistory table (metadata about what EF code-first migrations have been run against it etc) and can't find it. There is some reasonable coverage of this table here for some background/interest reading.
So to resolve the issue, I think the steps to take are:
Initialise your database so that it acknowledges the EF code-first stuff
Update the database, rolling forward all your migrations to date
I found some good coverage of how to do this here. This blog also has some good coverage of EF topics in general
PS. I am guessing that your .dsf/SQL Compact Edition database wouldn't have had this problem because EF code-first would have created it for you on first run so it was already acknowledged as being a code-first database.
Here is a link to Entity Framework Power Tools. It is made for creating models by 'Reverse Engineering' your Database on a remote server. You can then easily access this database using EF.
Reverse Engineer Code First - Generates POCO classes, derived DbContext and Code First mapping for an existing database
Both of the initializer methods which I had tried fail when the database already exists:
Database.SetInitializer<Context>(new Initializer());
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Context>());
However it is possible to force the database to be dropped using:
Database.SetInitializer(new DropCreateDatabaseAlways<Context>());
The following SO post provides the answer to my question:
Setting up a Entity Framework Code First Database on SQL Server 2008
I've tried a combination of the two, and have decided that the best solution is to manually go into SQL Management studio and DROP the database, and re-create it using the initializer as this allows me to Seed the contents of the database.
Database.SetInitializer<Context>(new Initializer());
See here for more information on Seeding the database as it is also quite an unstable processess!
How can I get my database to seed using Entity Framework CodeFirst?