I have a database called ApplicationName_Development running on SQL Server 2008 R2 Developer edition on my development box.
I added .NET membership tables to the database with no problem. When I tried to get Code First working I received the following error message:
The server encountered an error
processing the request. The exception
message is "Model compatibility cannot
be checked because the database does
not contain model metadata. Ensure
that IncludeMetadataConvention has
been added to the DbModelBuilder
conventions.
After some googling, I discovered that I had to delete the database and let EF create the database. That's fine but I lost all my .NET membership tables. I can go back in and add the membership tables again but if my model changes and EF needs to recreate the database then I have to add the membership tables in again.
How do I get around this?
This is how code-first work. Main idea of code first is that you do not touch your database because it is responsibility of the model to create the database. If you want to customize your database you must create custom IDatabaseInitializer and add your custom SQL.
public class MyDbInitializer : DropCreateDatabaseIfModelChanges<MyContext>
{
protected override void Seed(MyContext context)
{
// Here run your custom SQL commands
context.Database.ExecuteSqlCommand("CREATE TABLE ....");
}
}
Now you only need setup your cutom intializer on the startup of your application:
Database.SetInitializer<MyContext>(new MyDbInitializer());
If you don't want to do it this way you must manually maintain your database and set initializer to null.
Found a easier workaround here. I hope this helps.
http://www.paragm.com/ef-v4-1-code-first-and-asp-net-membership-service/
Another option could be to use the System.Web.Management namespace. I've had great success with the code below:
string connectionString = ConfigurationManager.ConnectionStrings["MyDatabaseContext"].ConnectionString;
string database = "MyDatabaseName";
SqlServices.Install(database, SqlFeatures.All, connectionString);
It will just create the database and after that you can add users with the standard membership API.
Here's another possibility.
If you look at the MvcMusicStore sample - there's a SampleData class that is responsible for seeding the database on a rebuild. The SampleData class inherits from DropCreateDatabaseIfModelChanges, and overrides the Seed method. This class is passed to the Database.SetInitializer in the Application_Start method in global.asax.
I was getting the same error as you until I changed the parent class of SampleData to CreateDatabaseIfNotExist.
Then you can override the Seed method to insert any data you desire at startup, without it blowing away the database.
While you are developing, create 2 databases and two connection strings. One for SqlMembership (using aspnet_regsql) and one for your EF Application. If you would like to merge them into a single DB in production, just change the connection string in web.config.release to be the same. Then, EF model changes will just drop your apps db and not your membership DB.
By treating your authentication component separately, you will naturally decouple your authentication system from your application system. Then, if you wish to change membership providers, you will be better setup.
As the system grows, you will likely need to support non-pure models without EF code first, so this is a good template for going down that path.
I found the easiest way without playing with anything else was the following.
I ran the application first time with DropAndRecreatedatabase always in the Initilizer.
This created my database for the first time.
Following this I changed this to DropCreateDatabaseIfModelChanges.
Related
Trying to build an application that uses ASP.NET Authentication with Identity.
I've been watching a video on how to do things. They add new properties directly to the ApplicationUser class and then update the database using code-first migrations.
But I'm using database first.
So I added my new properties directly to the ApplicationUser class, and I also added compatible fields to my database. But I still get an error.
The model backing the 'ApplicationDbContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).
I have Googled this and found articles specifically referencing database first, but they all seem to involve using code first!
Is this even possible to do without code first any more? Or is it just the case where we will all use code first or die?
As #Kyle suggested, this is all based on the __MigrationHistory table.
I'm not sure exactly how this all works, or what the overhead is if this table is being tested against my data each time I run my software. But renaming the table gets rid of the error. And I'm now able to modify the database as I wish without errors.
It takes a while (3 minutes+) to 'create/compile' my DbContext. The web server starts in about 5 seconds, but when I do the first query to my database, Entity Framework has to 'build/create/compile' the database in memory or something, I think? The next requests are almost instant. This was a Database First creation of the DbContext, the database already exists in MSSQL and has data. The DbContext contains about 500 DbSet's with relations.
Is there a way to speed this up by doing the 'creation(mapping?)' of my Entity Framework's DbContext before running the web server, create the file/mappings it needs, so the first request is fast too?
EDIT1:
I've tried the Power Tools, but they give me an error that the DbContext has no constructor that can be used, while it has a normal constructor
public DbContext() : base() {}
Any other things I could try?
The Entity Framework documentation describes how to generate views using EF Power Tool here.
Once you have in stalled EF Power Tools you have to:
Right click on the class containing your DbContext or on your .edmx file
Select "Generate Views"
This will generate the class containing the pre-computed mapping, which will automatically load on startup. If you change your database and don't regenerate the views EF will throw an exception.
Whether it will work for EF7 though, who knows...
I am following the offical asp.net "Getting started with EF 5 using MVC 4". In that tutorial, the database is created when the migrations are performed(in my understanding). When I was looking at the EF 5 with Mvc 5 tutorial they didn't use migrations to create a database. They use database initializer. So, I was wondering could create a database for your project without using migrations in EF 5? Also, what would the difference be with both these approaches?
Code first Migrations and using Package Manager Console Commands to do upgrades can get a bit confusing at first.
You can use the initializer to CreateDatabaseIfNotExists , DropCreateIfModelChanges, DropCreateDatabaseAlways and to MigrateDatabaseToLatestVersion
See the interface IDatabaseInitializer<TContext>.
CreateDatabaseIfNotExists // is the Default initializer.
So this is why it appears EF just does things for you sometimes.
So the answer is "YES you can "Create a Database without Migrations"
But the difference is not obvious and if you would do that long term is another question.
If you are using migrations. It would Update the Db to match the code first model.
If there is NO database, then that means creating the database.
So Thats why Automated migrations and CreateDB look confusing since they can result in same outcome sometimes. But technically they are different.
So generally it is sufficient to use code first automatic "migrations" only.
Migrations can be either Automatic or "managed".
The managed migrations approach invovles generating code , tweaking the code and running PM commandlet or POwershell command to actually perform the migration.
With Automated migrations you just need set the intitializer and Access the DBContext.
There are 2 parts to the process.
a) The DB Initializer step.
do this immediately before instantiating YourDBContext.
//eg
// DONT TOUCH MY DB or i break your back!
Database.SetInitializer(new ContextInitializerNone<YourDbContext>()); // Do Nothing,
// OR
// yes migrate my db to match my code please.
Database.SetInitializer(new MigrateDatabaseToLatestVersion<YourDbContext, YourMigrationConfiguration>()); // Set to migration is requested, see config class below
The Confirguration class specified when using Migration initializer looks like this
public class YourMigrationConfiguration<TContext> : DbMigrationsConfiguration<TContext>
where TContext : DbContext{
protected YourMigrationConfiguration() {
AutomaticMigrationsEnabled = true; // run it when needed. Do not wait for my PM Command
AutomaticMigrationDataLossAllowed = true; // if the new db look means dropping tables or columns go ahead and kill my data. So use this option with caution.
}
then just trigger the migration in code when required.
Context.Database.Initialize(true); // i place this inside a method on my UoW class
Code first Db initialization strategies.
Code first migrations recommended reading
Managed Migrations
There are many articles on the web on this topic.
I've created my objects in ASP.NET MVC4, and after running the application, only UserProfile table is auto created, not the other one corresponding my class.
Followed this advice: Entity Framework 4.1 Code First not creating tables and got this 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.
Question 1: What is the correct way to do this in Code First approach?
Question 2: Why is the built-in UserProfile created, and not the table for my object? What makes the difference?
Please read my answer here ... same situation I think. UserProfile table created, others not created. My guess is that you've switched to an actual MSSQL DB and not a local DB, but have not pointed your WebSecurity DB initialization to the new database.
I got this error in my asp.net webapi service when I call method Membership.ValidateUser(email, password);.
I am using EF 4.3.1. DB created using this code
using (var db = DbFactory.Get())
{
Console.WriteLine("Creating new database...");
db.Database.Create();
Console.WriteLine("Initializing with initial objects...");
db.Database.Initialize(true);
}
I get this error only once on first start of my service.
Does anybody know why it happens?
It sounds like you already have an object named 'Applications' in the database the first time your application starts.
Does the code snippet you provided only run at startup?
Try dropping the object through the database management engine, and then re-running your service.
The error is self-explanatory.
You are trying to create an object (ex: table, sp, view, etc.) that is named Applications but that object already exists in the database.
Maybe you didn't remove it after initial testing.
Providing you're trying to run it on the right project:
Check your migrations folder, the Up method of your InitialCreate class is probably trying to create the Application table. You can either
Drop the table and run the code again
or
Set up your InitialCreate properly to handle this scenario