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.
Related
I got an error using ASP.NET Identity in my app.
Multiple object sets per type are not supported. The object sets
'Identity Users' and 'Users' can both contain instances of type
'Recommendation Platform.Models.ApplicationUser'.
I saw a few questions about this error in StackOverflow. All indicate on two DbSet objects of the same type. But in my DbContext there aren't the same types of DbSets. Exception is thrown on FindAsync() method during logging in.
if (ModelState.IsValid)
var user = await UserManager.FindAsync(model.UserName, model.Password);
if (user != null && user.IsConfirmed)
{
The problem is I don't have two DbSets of the same type. My Contexts look like this:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
public System.Data.Entity.DbSet<RecommendationPlatform.Models.ApplicationUser> IdentityUsers { get; set; }
}
and
public class RecContext : DbContext
{
public RecContext()
: base("RecConnection")
{
Database.SetInitializer<RecContext>(new DropCreateDatabaseIfModelChanges<RecContext>());
}
public DbSet<Recommendation> Recommendations { get; set; }
public DbSet<Geolocation> Geolocations { get; set; }
public DbSet<Faq> Faqs { get; set; }
public DbSet<IndexText> IndexTexts { get; set; }
}
What could cause this problem? Maybe something connected with in-built ASP.NET Identity functionalities? Anyway, what is Users type? I don't have it in my app...
You do have two DbSets` of the same type.
IdentityDbContext<T> itself contains Users property declared as:
public DbSet<T> Users { get; set; }
You're declaring second one in your class.
review this file "ApplicationDbContext.cs", remove the line, generated automatically by scaffold last, should be like this:
public System.Data.Entity.DbSet<Manager.Models.ApplicationUser> IdentityUsers { get; set; }
This issue can arise from using scaffolding to create a View. You probably did something like this: View > Add > New Scaffold Item... > MVC 5 View > [Model class: ApplicationUser].
The scaffolding wizard added a new line of code in your ApplicationDbContext class.
public System.Data.Entity.DbSet<RecommendationPlatform.Models.ApplicationUser> IdentityUsers { get; set; }
Now you have two DbSet properties of the same type which not only causes an exeptions to be thrown in the FindAsync() method but also when you try to use code-first migrations.
Be very careful when using scaffolding or even better don't use it.
Comment the new generated Dbset from identity model class like below
// public System.Data.Entity.DbSet<SurveyTool.Models.ApplicationUser> ApplicationUsers { get; set; }
Whenever I see this problem, I always double check the DbSet. - ESPECIALLY if you are using another language for Visual Studio.
For us who use other language on VS, always double check because the program doesn´t create controllers or models with the exact name. perhaps this should be a thread.. or there is one already and I missed it.
I got an error using ASP.NET Identity in my app.
Multiple object sets per type are not supported. The object sets
'Identity Users' and 'Users' can both contain instances of type
'Recommendation Platform.Models.ApplicationUser'.
I saw a few questions about this error in StackOverflow. All indicate on two DbSet objects of the same type. But in my DbContext there aren't the same types of DbSets. Exception is thrown on FindAsync() method during logging in.
if (ModelState.IsValid)
var user = await UserManager.FindAsync(model.UserName, model.Password);
if (user != null && user.IsConfirmed)
{
The problem is I don't have two DbSets of the same type. My Contexts look like this:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
public System.Data.Entity.DbSet<RecommendationPlatform.Models.ApplicationUser> IdentityUsers { get; set; }
}
and
public class RecContext : DbContext
{
public RecContext()
: base("RecConnection")
{
Database.SetInitializer<RecContext>(new DropCreateDatabaseIfModelChanges<RecContext>());
}
public DbSet<Recommendation> Recommendations { get; set; }
public DbSet<Geolocation> Geolocations { get; set; }
public DbSet<Faq> Faqs { get; set; }
public DbSet<IndexText> IndexTexts { get; set; }
}
What could cause this problem? Maybe something connected with in-built ASP.NET Identity functionalities? Anyway, what is Users type? I don't have it in my app...
You do have two DbSets` of the same type.
IdentityDbContext<T> itself contains Users property declared as:
public DbSet<T> Users { get; set; }
You're declaring second one in your class.
review this file "ApplicationDbContext.cs", remove the line, generated automatically by scaffold last, should be like this:
public System.Data.Entity.DbSet<Manager.Models.ApplicationUser> IdentityUsers { get; set; }
This issue can arise from using scaffolding to create a View. You probably did something like this: View > Add > New Scaffold Item... > MVC 5 View > [Model class: ApplicationUser].
The scaffolding wizard added a new line of code in your ApplicationDbContext class.
public System.Data.Entity.DbSet<RecommendationPlatform.Models.ApplicationUser> IdentityUsers { get; set; }
Now you have two DbSet properties of the same type which not only causes an exeptions to be thrown in the FindAsync() method but also when you try to use code-first migrations.
Be very careful when using scaffolding or even better don't use it.
Comment the new generated Dbset from identity model class like below
// public System.Data.Entity.DbSet<SurveyTool.Models.ApplicationUser> ApplicationUsers { get; set; }
Whenever I see this problem, I always double check the DbSet. - ESPECIALLY if you are using another language for Visual Studio.
For us who use other language on VS, always double check because the program doesn´t create controllers or models with the exact name. perhaps this should be a thread.. or there is one already and I missed it.
I've been building a basic MVC application to begin to learn the ASP.NET MVC framework.
After doing some more reading last night, I learned about "dropcreatedatabaseifmodelchanges" and that sounded like what I want to use while I am in the early development phase.
So to do this in Global.asax I put the following code:
public class MyDbInitializer : DropCreateDatabaseAlways<SwaggersDB> {
}
Where "SwaggersDB" is my database context as follows:
namespace SwaggersMVC.Models {
public class SwaggersDB : DbContext{
public DbSet<Hostel> Hostels { get; set;}
public DbSet<Room> Rooms { get; set; }
public DbSet<Booking> Bookings { get; set; }
public DbSet<RoomBooking> RoomBookings { get; set; }
}
}
I was under the impression that now, when I add a new property to one of my model classes and re-run the application that the corresponding database table would be updated - however when I query the table it has not been added.
I have also enabled migrations via the package manager, and I was thinking that maybe this has been messing with my Database Initializer.
I have tried using "update-database" with migrations but it says it would result in a loss of data. I really don't care about losing data, I just want to recreate the database each time the application runs.
If you use the DropCreateDatabaseAlways initializer, it will do just that and drop and recreate your database each time. You can use the Seed() method in the initializer to repopulate needed tables. This is good up to the point you deploy at which time you would probably want to disable the initializer or switch to something like CreateDatabaseIfNotExists and then use migrations.
In the constructor of the Configuration() class in the migration you can add:
internal sealed class Configuration : DbMigrationsConfiguration<COPERSRMS.MVC.DataContexts.ApplicationDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(COPERSRMS.MVC.DataContexts.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" }
// );
//
}
}
and your database will be updated with each change. Then you can generate a script to update the previously deployed database that will do a compare from the initial schema.
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.