13

I know this should be simple, but I was unable to find correct tutorial or explanation on web on this subject. There is a lot of videos and posts about adding new column to an existing table, using code first approach, but I can not find any with step by step explanation on how to add whole new table into existing database. Which is weird, I was pretty sure that I will find many examples. Maybe my search criteria is bad. So if anybody has any good link or video, please share.

What I'm trying to do is to add table Post into existing Default Database, created by MVC 5 project. I've made model class first, named it Post and it has a simple definition:

public class Post
    {
        [Key]
        public int PostId { get; set; }
        public string PostText { get; set; }
        public byte[] ImagePost { get; set; }
        public byte[] FilePost { get; set; }
        public string TextPost { get; set; }
        public string UserId { get; set; }
    } 

Then I have first doubts. I know I should create DbContext, but if I want to hit an existing database, should I use existing DbContext, already created by default in Web.config file like this:

<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-StudentBookApp-20150114035149.mdf;Initial Catalog=aspnet-StudentBookApp-20150114035149;Integrated Security=True"
      providerName="System.Data.SqlClient" />

Or I should use all new DbContext created for Post class?

Anyhow I've tried it both, but no success. When I created this new context I was doing following in PMC:

Enable-Migrations
Add-Migration "PostMigration"
Update-Database

Usually, or all goes well, but I don't get any new table in database, or I get an error: AspNetUsers already exists, and AspNetUsers is one of auto-created tables that I've changed by adding new columns to it.

Update: My context right now is in seperated class named PostContext and it looks like this:

public class PostContext : DbContext
{
    public PostContext() : base("name=PostContext")
    {
    }

    public DbSet<Post> Posts { get; set; }
}

Second try:

Since my first approach didn't gave any result. I've tried doing what's described in this link. Adding mapping to my project:

I've crated new class PostConfiguration for mapping:

public class PostConfiguration : EntityTypeConfiguration<Post>
    {
        public PostConfiguration() : base()
        {
            HasKey(p => p.PostId);
            ToTable("Post");

            HasOptional(p => p.PostText);
            ToTable("Post");

            HasOptional(p => p.ImagePost);
            ToTable("Post");

            HasOptional(p => p.TextPost);
            ToTable("Post");

            HasOptional(p => p.FilePost);
            ToTable("Post");

            HasRequired(p => p.UserId);
            ToTable("Post");
        }
    }

In the class Post I've added context class too PostContext with modelBuilder variable as they've suggested in listed link above:

 public class PostContext : DbContext
    {
        static PostContext()
        {
            Database.SetInitializer(new DropCreateDatabaseIfModelChanges<PostContext>());
        }

        public DbSet<Post> Posts { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Properties()
                        .Where(p => p.Name == "Key")
                        .Configure(p => p.IsKey());

            modelBuilder.Configurations.Add(new PostConfiguration());
        }

   }

I've run all PMC commands again, and still no success, table Post is missing from default database.

Community
  • 1
  • 1
nemo_87
  • 4,523
  • 16
  • 56
  • 102
  • Did you add your class to your context? Can we see your context file? – Sefa Jan 15 '15 at 07:56
  • @vgSefa Sure, I've just updated my post and added PostContext class code :) – nemo_87 Jan 15 '15 at 08:01
  • This is SQL Server, right? (I'm asking because Migrations don't work with the ADO.NET provider for SQLite). – bvgheluwe Jan 15 '15 at 08:16
  • @bvgheluwe Yes it is. I mean it is a local database, but as I know VS 2013 uses SQL Server as default. :) And migrations did work when I was adding new columns to AspNetUsers table, so they are supported by this database for sure... I am missing some step, and don't have an idea what it can be...:( – nemo_87 Jan 15 '15 at 08:18
  • REname your DefaultConnection as PostContext – Sefa Jan 15 '15 at 08:21
  • @vgSefa Still nothing... I've did that run all migration commands in PMC and all it done is changed name of the local database from DefaultConnection to PostContext... P.S. In generated migratgion.cs file for Up() method I get empty body, and I think that this is where the CreateTable commands should be auto-generated... So I guess that migration doesn't recognize that there are any changes to model... – nemo_87 Jan 15 '15 at 08:26
  • you have only one connection and context, right? – Sefa Jan 15 '15 at 08:32
  • @vgSefa yes only that one that use to has a name DefaultConnection and now is PostContext... – nemo_87 Jan 15 '15 at 08:33
  • You said you have existing tables, but I only see `Posts` in your context – devqon Jan 15 '15 at 08:36
  • @devqon yes table is existing and auto-created in project...should I find auto-generated context to and add PostContext there? – nemo_87 Jan 15 '15 at 08:38

2 Answers2

21

What has happened here is that you had existing database tables before Migrations where enabled. So Entity Framework thinks that ALL your database objects need to created, this could be seen by opening up your PostMigration migration file.

The best way is to trick EF into to doing the initial migration with every before you added the Post table and then do the Posts migration after.

Steps

  1. Comment out the Posts in the DBContext so EF doesn't know about posts

    //public DbSet<Post> Posts { get; set; }
    
  2. Enable Migrations

    Enable-Migrations
    
  3. Add an initial migration with all tables prior to your changes

    Add-Migration "InitialBaseline" –IgnoreChanges
    
  4. Now update the database, this will create a MigrationHistory table so that EF knows what migrations have been run.

    Update-Database
    
  5. Now you can uncomment the line in 1 to "Do your change"

  6. Create a new migration with the addition of Posts

    Add-Migration "PostMigration"
    
  7. Now do an update... and hopefully it should all work.

    Update-Database
    

Now that migrations are all setup and they are baselined future migrations will be easy.

For more information I found this link useful: http://msdn.microsoft.com/en-us/data/dn579398.aspx

Community
  • 1
  • 1
Oliver
  • 35,233
  • 12
  • 66
  • 78
  • thanks for answering. :) I've tried what you've said, and still nothing. I was also trying a different approach to this problem, but also with no success. I will add that also into my edited post. :( @Oliver – nemo_87 Jan 15 '15 at 09:13
  • After Step 6 : If You not able to do so , Then go to Up Method in that Migration Configuration and Delete Code of Create Table .. Then Follow Step 7 : @nemo_87 – Ravi Mehta Dec 02 '15 at 08:46
  • Thank you so much for this! Exactly what I was looking for. I was having a hard time grasping the creation of new models. :) – CalebHC Apr 23 '16 at 18:10
0

You can resolve that by going to migration folder and delete Post-Migration file, then inside migration folder you will find a file named ApplicationContextModelSnapshot or something like that, then delete modelBuilder.Entity related to your post model. After that do:

Add-Migration "PostMigration"
Update-Database
Ali A. Jalil
  • 873
  • 11
  • 25