Add new table to an existing database using Code First approach in EF 6 and MVC 5 - asp.net-mvc

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.

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
Comment out the Posts in the DBContext so EF doesn't know about posts
//public DbSet<Post> Posts { get; set; }
Enable Migrations
Enable-Migrations
Add an initial migration with all tables prior to your changes
Add-Migration "InitialBaseline" –IgnoreChanges
Now update the database, this will create a MigrationHistory table so that EF knows what migrations have been run.
Update-Database
Now you can uncomment the line in 1 to "Do your change"
Create a new migration with the addition of Posts
Add-Migration "PostMigration"
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

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

Related

Entity Framework Database First Classes and Table Names

I am trying to add .edmx to my web api application. The table names in our database are long and cumbersome like tbl_Company, tbl_User_Logins, tbl_Company_Departments. I would like to use neat class names like Company, User, Departments that map to these tables. I have been trying to find sample code to do this, but I feel like I am not "asking the right questions" which is why I can't find any answer.
I tried creating classes for "Department" and "User", and I tried adding code like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Department>().ToTable("tbl_Company_Departments_xlu");
modelBuilder.Entity<User>().ToTable("tbl_User_Logins");
}
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<Department> Departments { get; set; }
but it didn't work when I tried to add a new department using Departments.Add(department). I am obviously missing a step, but I do not know what it is. I am new to this and am struggling. Any assistance is greatly appreciated.

Entity Framework creates an empty migration file

I created my initial project in Visual Studio and discovered I had used SQL Server after I created my initial migration. I then changed all the connection information to use MYSQL and connected successfully. I created the initial migration again and it created all the ASP security tables. I added a new model and updated the database, but it created an empty migration (just UP/DOWN methods)
I've tried multiple fixes I found here and other sites. I backed out the second migration and retried. I tried forcing the migration again (-f). I dropped the new MYSQL db and deleted the migrations then started over, all with the same result.
Here is my model code:
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace congresssucks_conversion.Models
{
public class BlogPost : DBContext
{
public int Id { get; set; }
public string Title { get; set; }
public string ShortPost { get; set; }
public string Post { get; set; }
public string Tags { get; set; }
public DateTime Updated { get; set; }
}
}
And here is the migration file:
namespace congresssucks_conversion.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class blogpost : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
}
It completes successfully and no errors in the Terminal Window.
You're combining two separate things, your model class and your database context.
Your BlogPostm class shouldn't inherit DbContext, it should be just a plain C# class.
Then you make a new class that looks something like this:
public class BlogDbContext : DbContext
{
public DbSet<BlogPostm> Posts { get; set; }
}
Now you have a class that can represent a single post, and another class that can represent a database with a table of multiple blog posts. The migration generator is looking for those DbSet<whatever> properties, so you should see real migrations after this change.
There are a lot more ways you can describe what you want Entity Framework to do with your database, so it would be worth reviewing an Entity Framework tutorial.
Try to delete a record of last migration from _MigrationHistory table. Maybe This record had been incorrectly created before added DbSet for the new model object to DbContext class. After this delete, new migration was created with correct Up() and Down() methods.

Models and EF are making them plural - hauler/haulers [duplicate]

This question already has answers here:
How do I singularize my tables in EF Code First?
(3 answers)
Closed 6 years ago.
This has happened twice on the same project. I'm using MVC/VS2015 community and I'm adding 2 classes: hauler and sale.
namespace CarThingy2.Models
{
public class Sale
{
public int ID { get; set; }
public int CoNbr { get; set; }
public int Locn { get; set; }
public int Ticket { get; set; }
public int Haul_Code { get; set; }
}
}
so I go to save - then I add the controller, and everything's good except I change the controller "title" (it was scaffolded as "SalesController") to SaleController. Run the project and it gives me an error about "it can't find dbo.Sales" in the "InnerException". I ended up having to enable-migrations, add-migration addsomethingelse and then finally update-database. TWICE (once for hauler, once for sale)!
Am I doing something wrong that grabs the "pluralized" name? This has happened to me before and I would least like an explanation as to why. The weirdest thing now is that the website will work, but the Tables ARE PLURAL (Haulers and Sales).
So were the tables originally called 'dbo.Sale' and 'dbo.Hauler'?
EF default convention is to use singular entity names and plural table names. You can manually specify the table name in the mapping though.
Note - now that you've added migrations, this will trigger another migration (or just delete the Migrations folder in the project and the dbo._MigrationHistory table in the database if you don't want migrations).
In the DbContext:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Hauler>().ToTable("Hauler");
modelBuilder.Entity<Sale>().ToTable("Sale");
}
If you have an existing database with all singular names, you can globally remove the pluralization convention in the above method as well:
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
Or via attribute on the entity:
[Table("Sale")]
public class Sale
{
}

Modeling an existing database

I want to generate a model based on an existing database -- I thought it would be as simple as writing the model, adding a DbContext class, and configuring a connection string:
namespace MyProject.Models
{
public class Account
{
public int Id { get; set; }
public string Email { get; set; }
public string Name { get; set; }
}
public class AccountDBContext : DbContext
{
public DbSet<Account> Accounts { get; set; }
}
}
With a simple boilerplate controller
public ActionResult Index()
{
return View(db.Accounts.ToList());
}
The boilerplate view, which I won't post here, which lists all of the members of the db object that we return.
ANd finally, a connection string:
<add name="AccountDBContext" providerName="System.Data.SqlClient" connectionString="[server connection string]" />
Only problem is I don't see any entries being displayed. It's definitely connecting, but not retrieving or displaying the data that the particular DB contains.. am I missing something?
Edit
Ok, so first thing is first: it wasn't connecting. I had a typo in my connection string name. It was hitting the default, and subsequently displaying nothing.
What I am getting now, though, is The model backing the 'AccountDBContext' context has changed since the database was created.
Is this because my model doesn't match exactly to what the database contains?
This is the "Code First with an Existing Database" scenario.
What version of EF are you using?
In EF 4.3 when you let code first create a database for you, it inserts a Migration-History table into the new database. It’s hidden in System Tables.This is equivalent to the EdmMetadata table you got with EF 4.1 & 4.2. But when you already have the database you can use code first migrations. (http://msdn.microsoft.com/en-US/data/jj591621)
Either way you should probably check if such a table exist. If it does you can delete it and then you'll be solely responsible to correctly matching your pocos to the database.
Another quick workaround i have found is putting
Database.SetInitializer<YourContext>(null);
to your Application_Start() in Global.asax
See also this similar question: Entity Framework Code Only error: the model backing the context has changed since the database was created

With Entity Framework 4.1 Codefirst, how do you create unmapped fields in the poco classes?

I have a set of classes as my domain objects.
I have a set of configuration files to map these objects (EntityTypeConfiguration<>).
When I add a property to any of the domain objects without mapping to a column, the dbcontext attempts to query for the column, ignoring the fact that it is not mapped.
I must be missing a setting either in the configuration code or the dbcontext code. I do not want to add an attribute to the poco class (decorating the pocos tie them to a specific persistence implementation, which I wish to avoid).
On the call against the IQueryable to populate a ticket object, the call fails with the message:
Invalid column name 'NotInDatabase'.
public class Ticket
{
public Ticket()
{
}
public virtual int Id
{
get;
set;
}
public virtual string Title
{
get;
set;
}
public virtual string Description
{
get;
set;
}
public string NotInDatabase
{
get;
set;
}
}
internal class TicketConfiguration : EntityTypeConfiguration<Ticket>
{
public TicketConfiguration()
{
ToTable("ticket_table_name");
HasKey(o => o.Id)
.Property(o => o.Id)
.HasColumnName("ticketId")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
.IsRequired();
Property(o => o.Title).HasColumnName("TicketTitle");
Property(o => o.Description).HasColumnName("TicketDescription");
}
}
Note:
Please do not suggest using "Database First" or "Model First" for my situation. I want to map poco objects to the database using the features of code first, even though I have an existing db structure. I am comparing this to nhibernate and really want to stick to a similar structure (since Microsoft "adopted" fluent nhibernate's approach, it's pretty easy to compare apples to apples).
Thanks!
.Ignore should do the trick or by attribute it's called [NotMapped]

Resources