I am working on a MVC project with entity framework in automatic migrations and trying to figure out how to update the database after new properties have been added.
I have this scenario.
Before:
public class X {
public int Id {get;set;}
public string Name {get;set;}
public bool IsChecked() {
... // some heavy duty routine
}
}
The code has been released and is working on the production environment but slow so I want to cache the method IsChecked. I alter my class:
public class X {
public int Id {get;set;}
public string Name {get;set;}
public bool Checked {get;set;}
public bool SetChecked() {
bool result = ... // some heavy duty routine
Checked = result;
}
}
Now I want to make an update script which executes the SetChecked on all items in the database.
What approach should be used?
If migration is enabled and set to auto, all you need to do is to add a new migration, in vs just open package-manager console and select the project from the drop down list and type this command:
add-migration "name-of-migration"
this will create a new class under migrations folder then you have to compile and upload new code to the server. After the first query the database will be updated.
Related
I have simple context with 3 tables.
database tables are already present but using code first approach.
Model Device.cs is -
public class Device
{
public System.Guid Id { get; set; }
public string Name{ get; set; }
}
public class sampledbContext : DbContext
{
public sampledbContext ()
: base("name=sampledbContext ")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public virtual DbSet<Device> Devices { get; set; }
}
To avoid extra s I have added above line into OnModelCreating but it is giving an error -
System.InvalidOperationException: 'The model backing the 'sampledbContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).'
Database was already created and I try to use code first approach here.
I have not done update-database yet.
I tried doing Enable-Migration and Update-database it creates table with name s like Devices why ? s is added ?
You've turned off auto-migrations in the line:
Database.SetInitializer<IoTSimulatordbContext>(null);
And therefore you will need to run update-database manually to update the model (you can run this via package manager console). If you have any data in your tables it is likely that the migration will fail due to the possibility of losing data, in that case you will need to either delete all data from the tables first or make a custom migration script to handle copying the data first. As this seems like a test it may be better to restart the migration project with the pluralisation off from the beginning.
You can add a DataAnnotation to describe the Schema and Table name to your Table class such as this;
[Table("Device", Schema = "MySchema")]
This will give you more control over the naming.
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.
I have an Azure Mobile Services project (C# backend) that I recently created and attached to an Azure SQL database. I have been trying to enable Code-First Migrations on that backing database, but it throws errors when I try to update the database.
I ran through all of the conventional steps to enable migrations (Enable-Migrations, Add-Migration). But when I try to Update-Database, it returns the following error:
Cannot create more than one clustered index on table 'dbo.Appointments'. Drop the existing clustered index 'PK_dbo.Appointments' before creating another.
Why is this happening? There aren't any tables in my database, and the project is pretty much the default.
Several of the answers about deriving from a custom entity class will work, but they are not the ideal solution. As the EF team (and others) have mentioned, you need to simply add this line to your Context Configuration constructor.
SetSqlGenerator("System.Data.SqlClient", new EntityTableSqlGenerator());
This will remove your errors when creating migrations and allow you to update the database via powershell command.
If you are getting this error on update-database after creating the migration class, Then have a look # your migration class. The migration class will take primary is clustered index. So remove that from the up() method.
.PrimaryKey(t => t.Id, clustered: false)
.Index(t => t.CreatedAt, clustered: true);
If you using it on azure mobile service, do not call 'update-database' manually.
refer http://azure.microsoft.com/en-in/documentation/articles/mobile-services-dotnet-backend-how-to-use-code-first-migrations/
I was fighting with this problem today for a few hours. Until I found this link:
How to make data model changes to a .NET backend mobile service
If you follow the instructions there, it will definitely work. The main thing is, that the migration will take place, when you hit F5 during a local debugging session.
I just had the same issue.
It is caused by the definition of EntityData that is our base class:
public class OrgTest : EntityData
{
public string Prop1 { get; set; }
}
I replaced EntityData with my own implementation "CustomEntity" where I removed the attribute [Index(IsClustered = true)] on the CreatedAt column:
public abstract class CustomEntity : ITableData
{
// protected CustomEntity();
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[TableColumn(TableColumnType.CreatedAt)]
public DateTimeOffset? CreatedAt { get; set; }
[TableColumn(TableColumnType.Deleted)]
public bool Deleted { get; set; }
[Key]
[TableColumn(TableColumnType.Id)]
public string Id { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
[TableColumn(TableColumnType.UpdatedAt)]
public DateTimeOffset? UpdatedAt { get; set; }
[TableColumn(TableColumnType.Version)]
[Timestamp]
public byte[] Version { get; set; }
}
and now I inherit from this one:
public class OrgTest : CustomEntity // EntityData
{
public string Prop1 { get; set; }
}
Probably I will have troubles further on, but for the time being I can create my model!
Hope you can also start like this!
See this article:
avoid nightmares using ef first migration in azure mobile services
EntityData define a cluster indext to CreateAt and Id is by default a cluster index, this way it provide an error and you should define only one.