I keep getting the following error:
System.InvalidOperationException: The model backing the 'McContext'
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 am creating an .NET MVC 5 website using the latest Entity Framework from nuget, v6.1.3. I am attached to a local MDF file as I don't have SQL Server or Express installed locally. I am using the Code First model.
I spent hours yesterday and today combing through SO and WWW posts on this error, but have not found a solution that works. Most of them revolve around different types of Initializers, or short explanations about how code first requires migrations or initializers for model changes. But I am running the setup manually through the PM console. I have included my steps below.
Connection String:
<add name="testSQLConnection" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\jwatts\Documents\Visual Studio 2015\Projects\MyProject\Databases\MyProject01.mdf;Integrated Security=True;Connect Timeout=30" providerName="System.Data.SqlClient" />
The model:
public class Family
{
public Family() { }
[Key, Index(IsUnique = true)]
[Column(Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[StringLength(128)]
public string Name { get; set; }
[StringLength(1024)]
public string Description { get; set; }
public DateTime Created { get; set; }
public string CreatedBy { get; set; }
public DateTime? Changed { get; set; }
public string ChangedBy { get; set; }
public DateTime? Deleted { get; set; }
public string DeletedBy { get; set; }
}
The Context:
public class McContext : DbContext
{
public McContext() : base("testSQLConnection") { }
public DbSet<Family> Families { get; set; }
}
The configuration:
internal sealed class Configuration : DbMigrationsConfiguration<Data.McContext>
{
public Configuration()
{
MigrationsDirectory = #"Data\Migrations";
AutomaticMigrationsEnabled = false;
AutomaticMigrationDataLossAllowed = false;
}
protected override void Seed(McContext context)
{
context.Families.Add(new Family()
{
Name = "My Family",
Description = "The family",
Created = DateTime.Now,
CreatedBy = "system"
});
context.SaveChanges();
}
}
Auto generated migration class:
public partial class StartupConfig : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Families",
c => new
{
Id = c.Int(nullable: false, identity: true),
Name = c.String(nullable: false, maxLength: 128),
Description = c.String(maxLength: 1024),
Created = c.DateTime(nullable: false),
CreatedBy = c.String(),
Changed = c.DateTime(),
ChangedBy = c.String(),
Deleted = c.DateTime(),
DeletedBy = c.String(),
})
.PrimaryKey(t => t.Id)
.Index(t => t.Id, unique: true);
}
public override void Down()
{
DropIndex("dbo.Families", new[] { "Id" });
DropTable("dbo.Families");
}
}
Unit test code:
[TestMethod]
public void CreateTheContext_Test()
{
using (var ctx = new McContext())
{
//error on this line below:
var fam = ctx.Families.Where(f => f.Name.Contains("My")).FirstOrDefault();
Assert.IsTrue(fam != null && fam.Name.Contains("My"));
}
}
Recreation steps:
I started with a "clean slate" and deleted all database tables in my test database, and deleted all Data\Migrations.
Rebuilt the solution. (The base project and a unit testing project)
In Package Manager Console, ran "Add-Migration StartupConfig"
A migration file is added to Data\Migrations called "{datetime}_StartupConfig.cs". See StartupConfig class above.
I built the project.
I ran "Update-Database -TargetMigration:StartupConfig"
The PM console outputs 4 lines, including the "Running Seed method", and completes successfully.
I confirmed via SQL query that the "__MigrationHistory" and "Families" table have been added to the database, and each table has 1 record.
I ran the unit test and receive the error.
I had a more complex model, but I began removing things one by one making things as simple as I could. But I can't get any simpler than this, and yet the error persists. Of note, for this particular project I have never gotten a successful query out of the unit test.
As I was typing out these recreation steps above, I was performing the steps at the same time, and got the same error.
I am at a loss as to what to try next?
Since you'r code it's not changing it has to be something with the Migrations table (the one that has info of your db model) or with the DB file you're using.
I will suggest to install Sql server express and try everything again. Since the database you're making is a file you will have more risk with it.
Edit:
Try to see the name of the instances your projects are using. By default EF use DefaultConnection. Check the web.config or configuration files in all your projects.
In checking the connection string in the Unit Test per #AaronLS suggestion, I found that the connection string was different.
Turns out, the App.config for the Unit Test did not have the connection string and was treating "sqlTestConnection" as the database name since it could not resolve it otherwise.
Adding the connection string to the App.config resolved the issue.
Related
I've been trying for awhile to figure out how to use a single DBContext to create multiple tables in a Code First fashion without any luck. I'm sure it's just my unfamiliarity with the framework but I'm not sure what I'm missing. Here's a simple example with entities and the DBContext.
[Table("MyEntity")]
public class MyEntity
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public string MyColumn { get; set; }
public int MyNumber { get; set; }
}
[Table("MySecondEntity")]
public class MySecondEntity
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public string MyColumn { get; set; }
public int MyNumber { get; set; }
}
public class MyContext : DbContext
{
public DbSet<MyEntity> MyTable { get; set; }
public DbSet<MySecondEntity> MyTable2 { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var connectionStringBuilder = new SqliteConnectionStringBuilder {DataSource = "test.db"};
var connectionString = connectionStringBuilder.ToString();
var connection = new SqliteConnection(connectionString);
optionsBuilder.UseSqlite(connection);
}
}
It looks to me like it should work, but when I call it in the below code it blows up with a 'no such table: MyEntity' Sqlite exception when hitting the first foreach loop.
static void Main(string[] args)
{
using (var db = new MyContext())
{
MyEntity testEntity1 = new MyEntity();
MySecondEntity entity1 = new MySecondEntity();
testEntity1.MyColumn = "Test Data 1";
testEntity1.MyNumber = 12345;
db.MyTable.Add(testEntity1);
db.Database.Migrate();
entity1.MyColumn = "New Data 1";
entity1.MyNumber = 2;
db.MyTable2.Add(entity1);
db.Database.Migrate();
Console.WriteLine("Inserting Data...");
Console.WriteLine("Data in the Database");
foreach (var entity in db.MyTable)
{
Console.WriteLine("Id: " + entity.Id);
Console.WriteLine("Column Data: " + entity.MyColumn);
Console.WriteLine("Number: " + entity.MyNumber);
}
foreach (var entity in db.MyTable2)
{
Console.WriteLine("Id: " + entity.Id);
Console.WriteLine("Column Data: " + entity.MyColumn);
Console.WriteLine("Number: " + entity.MyNumber);
}
}
Console.WriteLine("Examples run finished,press Enter to continue...");
Console.ReadLine();
}
I can almost guarantee it's something simple I'm missing but I just can't seem to find it, and there aren't any examples I can find in their documentation. There seems to be a similar issue submitted on GitHub here https://github.com/aspnet/EntityFramework/issues/2874 but that's for multiple contexts. So maybe this is another piece that just hasn't quite made it to release yet?
Solution
By following the tutorial posted on http://ef.readthedocs.org/en/latest/getting-started/uwp.html as suggested by #natemcmaster and the solution recommended by #lukas-kabrt I was able to get it to work as desired. By running the below commands I was able to get the tables created and insert/select data from them.
Install-Package EntityFramework.Commands –Pre
Add-Migration MyFirstMigration
Update-Database
Check out Getting Started on UWP - EF 7 in the official docs. The following notes are from that document.
The default path on UWP is not writable. Your DB file needs to be in ApplicationData.Current.LocalFolder
options.UseSqlite("Data Source=" + Path.Combine(ApplicationData.Current.LocalFolder.Path, "blogging.db"))
Also, take note that on UWP you cannot run migrations from commands. You need to run them in the app.
using (var db = new BloggingContext())
{
db.Database.Migrate();
}
The DbContext class contains configuration of your database - tables, relationsships, etc. To use the DbContext you need to create a database that matches your DbContext. In the Code-first world, it is done by database migrations.
For ASP.NET 5 you need to add this configuration to your project.json file
"commands": {
"ef": "EntityFramework.Commands"
}
and then add a migration to your project and apply this migration to the DB by running following commands
dnx ef migrations add MyFirstMigration
dnx ef database update
For Full .NET you need to run following commands in the Package Manager Console (Tools ‣ NuGet Package Manager ‣ Package Manager Console)
Install-Package EntityFramework.Commands –Pre
Add-Migration MyFirstMigration
Update-Database
I'm having an issue with the current project I'm working on. It works fine and runs without error with it's current classes and functionality. My issue is that I can't seem to add another model, it's corresponding controller and views and get it to actually work.
Usually I would simply add a new model class to the folder, update my dbcontext class with a dbset with the new model as datatype. Then write "update-database -force" in the package manager console and it would apply the automatic migrations. But for some strange reason I can't seem to comprehend, it simply won't do that anymore.
Instead, after I create the model and add the dbset and then trying to update database it runs the update fine, but it doesn't add any new migrations. The funny thing is when I run the project I get the usual error you always get when you have forgotten to update the database where it's recommending code first migrations etc.
I tried checking my config file and it seems the context key is set to applicationuser instead of the proper dbcontext class, which I'm sensing is why it doesn't detect any changes(usually it figures this out itself?). But when I try changing it to the proper one and updating the database again, it gives me an error saying something about asproles is already in the database?
I'm completely lost here and would appreciate any input an experienced vs13 user can give me.
EDIT:
I should mention I have been working on the identity framework recently, which is probably why it has automatically changed the contextkey? But I haven't had any issues during that with any of my existing classes.
NEW EDIT (29-01-2015)
Relevant part of configuration file:
internal sealed class Configuration : DbMigrationsConfiguration<MEV3.Models.ApplicationDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
ContextKey = "MEV3.Models.QuestionContext";
}
protected override void Seed(MEV3.Models.ApplicationDbContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
this.AddUserAndRoles();
}
My QuestionContext file:
namespace MEV3.Models
{
public class QuestionContext : DbContext
{
public DbSet<ExamSet> ExamSets { get; set; }
public DbSet<BlanketSet> BlanketSets { get; set; }
public DbSet<LooseQuestionCase> LooseQuestionCases { get; set; }
public DbSet<Medcase> Medcases { get; set; }
public DbSet<Question> Questions { get; set; }
public DbSet<QuestionChoice> QuestionChoices { get; set; }
public DbSet<QuestionBeforeAfter> QuestionBeforeAfters { get; set; }
public DbSet<Answer> Answers { get; set; }
public DbSet<Tag> Tags { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Institution> Institutions { get; set; }
public DbSet<ExamType> ExamTypes { get; set; }
public DbSet<NewsArticle> NewsArticles { get; set; }
//public DbSet<TaskRecord> TaskRecords { get; set; }
//protected override void OnModelCreating(DbModelBuilder modelBuilder)
//{
// modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
//}
}
My ApplicationDbContext file:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
public DbSet<TaskRecord> TaskRecords { get; set; }
}
When I have the contextkey set to my QuestionContext and try to make changes to any models in that dbset, it gives me an error about the taskrecords (which is strange cuz they are inside the applicationdbcontext class).
This means I can't make any succesful updates of the database if I try to change a model in the QuestionContext.
If I set the contextkey to ApplicationDbContext I can make changes to anything in the applicationdbcontext succesfully, but it wont register any changes done in any of the models in the QuestionContext.
I'm at a loss, the way it works now it seems I can only add new models to the applicationdbcontext or change models in it, can't go back and alter anything in the questioncontext. Any thoughts?
Automatic migrations are succesfully enabled on both contexts btw. I've used this setup succesfully before I started fiddling with the identityframework.
Your application has more than one context, therefore you should tell Update-Migration which configuration to chose from. If the two contexts are in different projects, you can use the -ProjectName <string> command. Otherwise, use the -ConfigurationTypeName <string> command, making sure your configuration classes have different names. Also, make sure your QuestionContext's Configuration is public. More information here.
Also, make sure the connection string is pointing to the right Database when you run the project (under your current build configuration).
Finally, I would recommend you Enable-Migrations as forcing it like you do can lead to data loss.
My problem lies in the lack of experience in MVC. Basically, I have two tables in DB
-Person
-Offer
For each I have created a model and a controller and a model, so the structure looks like that:
public class Offer
{
public int OfferID { get; set; }
public string OfferTitle { get; set; }
public string State { get; set; }
public string Description { get; set; }
}
public class OfferDBContext : DbContext
{
public DbSet<Offer> Offers { get; set; }
}
This is the Offer model.
public class Person
{
public int PersonID { get; set; }
public string Username { get; set; }
public DateTime Birthday { get; set; }
public string Education { get; set; }
public string Email { get; set; }
}
public class PersonDBContext : DbContext
{
public DbSet<Person> Persons { get; set; }
}
This is the Person model.
Firstly I created the Person model, that added itself to db without any problems. Then I wanted to add Offer table, and I had to use the DropCreateDatabaseIfModelChanges method. I used it for OfferInitializer and PersonInitializer and then there is the Global.asax.cs file
protected void Application_Start()
{
Database.SetInitializer<OfferDBContext>(new OfferInitializer());
Database.SetInitializer<PersonDBContext>(new PersonInitializer());
//Database.SetInitializer<PersonDBContext>(new PersonInitializer());
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
From what I understand, I cant do that simply because I am dropping database 2 times, each time populating only one table at a time. How do I reorganize it all, so that I can populate both or more tables at a time, or the whole database?
First things first, you should not create individual DbContext classes for each table. You should instead put all your DbSets in the same DbContext. Doing this will simplify things greatly for you.
Secondly, you should look into using migrations. You should start using them very early in your project.
You work with code first migrations using the Package Management Console.
enable-migrations
Does exactly what the name implies. Initializes migrations in your project. This will create a folder inside your project and generate the files needed.
add-migration InitialCreate
This creates a migration. InitialCreate is actually a string and you can change it to whatever you want. This command will generate the scripts needed to create the database from strach.
update-database
This command verifies the database and applies the migration (or migrations - there can be multiple) required in order to get the database up-to-date.
This is the initial setup. If you do further changes to your first code first classes, or add more, you will just have to add a new migration and then execute it.
add-migration AddedFirstName
update-database
It's that simple!
There are some more advanced concepts like seed, rollback, update to specific migration, etc., but what I have typed above covers the basics and the day to day usage of migrations.
I recommend you to read this article which explains everything in much more detail: http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/migrations-and-deployment-with-the-entity-framework-in-an-asp-net-mvc-application
I am trying to run the code first migration in entity framework 6.0. I have added 4 new entities in my entities modal. However when i run the "add-migration" command in VS 2013, the generated migration file contains the script of all entitles (just like the initial migration) in my modal, though they are already in linked database. Obviously when I rum "Update-Database" commends, it generates entity already exists error. My DBContext class looks like following:
public class BidstructDbContext : DbContext
{
public BidstructDbContext() : base(nameOrConnectionString: "Bidstruct")
{
this.Configuration.LazyLoadingEnabled = false;
}
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<Permission> Permissions { get; set; }
public DbSet<Company> Company { get; set; }
// New Added Table
public DbSet<Gadgets> Gadgets { get; set; }
public DbSet<Language> Language { get; set; }
public DbSet<LanguageKeys> TranslationKeys { get; set; }
public DbSet<Translations> Translations { get; set; }
static BidstructDbContext()
{
Database.SetInitializer(new DatabaseInitializer());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
}
and DatabaseInitializer class looks like as following:
public class DatabaseInitializer :
// CreateDatabaseIfNotExists<BidstructDbContext> // when model is stable
DropCreateDatabaseIfModelChanges<BidstructDbContext> // when iterating
{
private const int AttendeeCount = 1000;
// EF is NOT a good way to add a lot of new records.
// Never has been really. Not built for that.
// People should (and do) switch to ADO and bulk insert for that kind of thing
// It's really for interactive apps with humans driving data creation, not machines
private const int AttendeesWithFavoritesCount = 4;
protected override void Seed(BidstructDbContext context)
{
}
}
Any idea, how to resolve this problem. Its was working fine for me few days back but now I am facing this problem :(
Check to see if your context keys have changed, in your migration history.
I'm working on a project that has been using automatic migrations, but the automatic migration was not occurring due to a lot of class changes. In trying to switch to non-automatic migration, Add-Migration was regenerating the entire schema.
So I tried putting the manual table changes into the Up() of the DbMigration, and this applied a migration and an entry into the __MigrationHistory table, but with a different context key (the namespace and class name of my configuration file.)
A quick test of renaming the previous (older) migration record's context key to be the same as the current one caused the migration up/down to generate correctly.
Even then...it may not be 100%. Most of my changes were correct, but it started out adding a table which already existed, then turned around and removed it.
I develop my ASP.NET MVC4 app using EF Code-first, also im using Migrations feature. I have specific entity and i want to set explicit id values for some reasons. How can i do this? I tried to mark id property with attribute like this:
public class NewsSource
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public string Title { get; set; }
public string WebSiteUrl { get; set; }
}
Then i add corresponding migration, delete database and try to update database using Seed() method like this:
context.NewsSources.AddOrUpdate(x => x.Title,
new NewsSource {Id = 654, Title = "ABC", WebSiteUrl = #"http://www.abc.com/"},
new NewsSource {Id = 22, Title = "XYZ", WebSiteUrl = #"http://XYZ.ru/"});
And ive got this error: "Cannot insert explicit value for identity column in table 'NewsSources' when IDENTITY_INSERT is set to OFF". How can i set identity_insert to ON using EF and migrations. As i understood from many topics its impossible and i have to use direct SQL-commands. Am i wrong?
I had a problem when I tried to change a column to an IDENTITY field when it was originally not an identity field. See this question and this one. You have to remove the column and recreate it to remove IDENTITY so fixing up foreign keys etc is probably a step too far for Entity Framework to do in a migration. You will have to alter the Up() and Down() methods yourself, or you may get away with doing it in the database.
What happens if you remove the DatabaseGenerated attribute and just leave the [Key] attribute?
public class NewsSource
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string WebSiteUrl { get; set; }
}
I ran into this issue awhile back and I believe this was a work around for me. I can't test it now since I don't have any projects in front of me with EF in them. All I can say is EF code first and the nuget migrations package is a great thing, if you treat it the way you are supposed to treat it. I have gotten myself into a number of WTF moments when using the two together and trying to seed complex related models. Good luck!