Scaffolding migration up/down shows Empty - c#

I want to create a new datatable in my database.
I ran Add-Migration items, it shows empty for both up() and down()
namespace myapp.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class items : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
}
I have a model:
public class Item
{
public string name { get; set; }
public int defineindex { get; set; }
}
public class ItemContext : DbContext
{
public DbSet<Item> Items { get; set; }
}
I also created a mapping when the above code doesnt generate useful scaffold. But it still didnt solve my problem.

There is a ContextKey value in my Migrations/Configuration.cs for my EF, which is set to a class name. So my EF will only care about that class. I need to put my DbSets all under that class for it to work instead of creating a new class.

Related

Update database without migration in Entity Framework

I've created an ASP.NET MVC sample application in Visual Studio. I added two classes like below :
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public int Price { get; set; }
public ICollection<Product> Products { get; set; }
}
public class Order
{
public int Id{ get; set; }
public Product Product { get; set; }
public int ProductId { get; set; }
public DateTime RegisterDate { get; set; }
}
and then I added two DbSet to the main DbContext like this:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public IDbSet<Product> Products { get; set; }
public IDbSet<Order> Orders { get; set; }
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
But now when I run project, I get this error :
The model backing the 'ApplicationDbContext' context has changed since the database was created
I just wanted to know is there a way to update the database without using migrations (Add-migrations and update-database)?
You can update the database structure in the way you want (queries, via DBMS user interface and so on).
If you do so you need to disable configuration check.
Database.SetInitializer<YourContext>(null);
(I insert this in a static constructor in the context)
You can enable automatic migrations to achieve this. This approach definitely uses code-first migration but you don't need to use Add-Migration command or update-database.
Run Enable-Migrations –EnableAutomaticMigrations from package manager console first to generates a Configuration class as follows:
internal sealed class Configuration : DbMigrationsConfiguration<ApplicationDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(ApplicationDbContext context)
{
}
}
Now you could either update the db context's constructor to migrate to latest version as follows:
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
Database.SetInitializer(
new MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>());
this.Database.Initialize(true);
}
Or migrate to the latest version on application start up as follows:
using (var context = new ApplicationDbContext())
{
Database.SetInitializer(
new MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>());
context.Database.Initialize(true);
}
UPDATE
If you prefer not to use migrations at all, you may consider setting the database initializer to null and handle the db migration manually using scripts
Database.SetInitializer<YourContext>(null);
With EF6:
I think what you can do it to have the Database.SetInitializer in your DbContext Class constructor to have the database created on the first run. This I guess you already have, next you can comment it where it says Database.SetInitializer<MyContext>(new CreateDatabaseIfNotExists<MyContext>());
and delete the dbo.__MigrationHistory table created in your database.
Now you can use Alter Table.. to add remove columns in your database table then in your C# Table class to match.

How do I solve this Entity Framework CodeFirst Context.SaveChange() DbUpdateException

I have a C# project using Entity. I am new to the Entity Framework. I have a singleton class called Project
public sealed class Project
{
public int Id {get; private set}
public static Project Instance { get; private set; }
public string Directory { get; private set; }
public string Name { get; private set;
public void Write()
{
using (var context = new DataContext(new System.Data.SQLite.SQLiteConnection(dbPath), false)
{
context.Projects.Add(this);
context.SaveChanges(); //when only Project is included in my database this works great, but an exception is thrown here whenever I include other classes.
}
}
}
The above class writes to a Projects table beautifully provided I don't try to write any additional tables to the database. However, I get an DbUpdateException whenever I try to add additional classes to the database. For instance, I have an abstract FunctionBase class, a concrete implementation of that class called OrdinatesFunction, an abstract decorator that also implements the FunctionBase while being composed of an OrdinatesFunction, and finally concrete implementations of the abstract Decorator (for instance the OutflowFrequencyDecorator class below). I would like to write the concrete decorators to the database. This shows the basic structure of my codebase:
public abstract class FunctionBase
{
public int Id { get; private set; }
public abstract bool IsValid {get; protected set; }
public void Write()
{
using (var context = new DataContext(new System.Data.SQLite.SQLiteConnection(dbPath), false)
{
context.Functions.Add(this);
context.SaveChanges();
}
}
}
public sealed OrdinatesFunction: FunctionBase
{
public override bool IsValid {get; protected set;}
public Statistics.CurveIncreasing Function {get; private set}
}
public abstract Decorator: FunctionBase
{
public virtual FunctionBase Function { get; set; } //this is a required navigation property I think.
public override bool IsValid { get; protected set; }
}
public sealed OutflowFrequencyDecorator: Decorator
{
public override bool IsValid { get; protected set; }
}
My default assumption with Entity (when my App.Config works and I can write a database file) is that the issue lies in my implementation of the DbContext. This is my DbContext implementation:
public class DataContext: DbContext
{
public DbSet<Projects>
public DbSet<FunctionBase> Functions { get; set; }
public DbSet<OutflowFrequencyDecorator> { get; set; } //I've tried it with and without this and if fails the same way in both instances.
public DataContext(DbConnection connection, bool contextOwnsConnection): base(connection, contextOwnsConnection)
{
}
public override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Project>();
modelBuilder.Entity<FunctionBase>();
modelBuilder.Entity<OutflowFrequencyDecorator>().HasRequired(t=> t.Function);
var sqLiteConnectionInitializer = new SQLite.CodeFirst.SqLiteCreateDatabaseIfNotExists<DataContext>(modelBuilder);
SetInitializer(sqLiteConnectionInitializer);
}
}
At this point I'm pretty lost. I've spent a few hours reading through advice on this site and others. While a lot of folks are encountering the same exception on the same command using Entity, the examples and (I think) reasons seem to be unrelated to my specific issue, or the advice is sparse or contradictory. Any help you could provide would be greatly appreciated... thanks in advance.

In code first "ies" (plural) is mandatory

Here im trying to get data from database using code-first but if I have a tabel Like Country, like this:
public class Country
{
public int id { get; set; }
public string Name { get; set; }
}
contextdb
public class ContextDb: DbContext
{
public ContextDb() { }
public DbSet<Country> Country { get; set; }
...
}
when I implements as Countrys its throwing an error:
Countries not have dbo
Please try to make it explicit which specific table you want for this particular type
public class ContextDb : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Country>().ToTable("Country");
}
public ContextDb() { }
public DbSet<Country> Country { get; set; }
}
As an alternative, you can turn off the pluralizing convention
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
Another option, as mentioned in Stefan's answer, is to have an attribute over your model class (which makes the class "not-that-POCO-anymore" but technically is perfectly valid).
Usually we use plurals in the DbContext like this:
public DbSet<Country> Countries { get; set; }
EF uses an auto plural convention, so your entity
public class Country
will translate to a datatable [dbo].[Countries] in your database.
If you want to explicitly override the name of the table in the database you can use the following attribute.
[Table("YourNameHere")]
public class Country
{
public int id { get; set; }
public string Name { get; set; }
}
I think there is a mixup in this logic somewhere in your code.
Alternativly you can also put your table in a differnt schema if you like:
[Table("YourNameHere", Schema = "YourSchemaNameHere")]
public class Country
{
public int id { get; set; }
public string Name { get; set; }
}
Beware with renaming the schema though, I have experienced that some migrations will break because to database index names are not always handled correctly.
note
See #Wiktor Zychla 's solution to disable the plural conventions on the whole context.

Entity Framework Migration - Column not being migrated

I've added a new property in my entity and ran the command to generate a new migration, but the generated migration contains nothing. Looks like EF did not detect the column add. Is there something else I need to do in order to get the column added in the migration? This is my class:
public class Group
{
public int Id { get; set; }
public int OrganizerId { get; set; }
public string Name { get; set; }
public string ImageUrl { get; set; }
public bool IsOnline { get; set; }
public virtual User Organizer { get; set; }
public virtual ICollection<GroupParticipation> GroupParticipations { get; set; }
public virtual ICollection<Question> Questions { get; set; }
public virtual ICollection<Subject> Subjects{ get; set; }
}
I have isolated the property I'm trying to add, which is "IsOnline". After adding it to the class and compiling the project, I run the following command:
Add-Migration AddGroupIsOnline
It correctly generated a new migration but here's how the migration looks like:
public partial class AddGroupIsOnline : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
The Up and Down does nothing. It should have added my property, is my assumption correct?
Any idea on what may be happening?
Thanks for all the help!
Ok, so I found the "problem". Basically an automatic migration has happened in some moment after I added the IsOnline property in my Group class. Therefore when I ran Add-Migration AddGroupIsOnline, no changes were detected (because it was already changed by automatic migration).
I ended up finding the answer by looking at my database table and the column was already there. Then I looked at the migration table, that gets created once DB Migrations are activated, and I found the following line:
Then I removed the IsOnline column, deleted the Automatic Migration record from the database and then re-ran:
Add-Migration AddGroupIsOnline
And here is the result:
public partial class AddGroupIsOnline : DbMigration
{
public override void Up()
{
AddColumn("dbo.Groups", "IsOnline", c => c.Boolean(nullable: false));
}
public override void Down()
{
DropColumn("dbo.Groups", "IsOnline");
}
}
So my self tip here is: if nothing is shown in the migration, there is nothing to be migrated. Verify the database and the automatic migrations in the [__MigrationHistory] table.

Entity Framework Code First MySql Pluralizing Tables

I am using the Microsoft Entity Framework with code first to manage my data (with MySQL). I have defined a POCO object, however, when I try to add data it says table Users doesn't exist. I looked in the DB and it created table User not Users. How can I remedy this? It is driving me nuts!
Thanks!
public class User
{
[Key,Required]
public int UserId { get; set; }
[StringLength(20), Required]
public string UserName { get; set; }
[StringLength(30), Required]
public string Password { get; set; }
[StringLength(100), Required]
public string EmailAddress { get; set; }
[Required]
public DateTime CreateDate { get; set; }
[Required]
public bool IsActive { get; set; }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
namespace YourNamespace
{
public class DataContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder dbModelBuilder)
{
dbModelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public DbSet<User> User { get; set; }
}
}
I have not used MySQL with EF yet but regardless I think the solution is unbias. You need to turn off Pluralize Table Convention.
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions.Edm.Db;
public class MyDbContext: DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Now EF will look for the literal of your object name to the table name.
Some great video tutorials are at http://msdn.microsoft.com/en-us/data/aa937723 under the Continue Learning Entity Framework. For additional learning experience, you can not specify the above but rather explicitly map the object 'user' to the table 'user'.
Additional References:
http://blogs.msdn.com/b/adonet/archive/2010/12/14/ef-feature-ctp5-fluent-api-samples.aspx
You can put an attribute on the class telling the name of the table:
[Table("Users")]
public class User
{
//...
}
...or you could use the fluent API. To do this you will override the OnModelCreating method in your DbContext class.
public class MyDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().Map(t => t.ToTable("Users"));
}
}
In future versions of EF, we've been promised the ability to write our own conventions. Thats not in there yet as of version 4.1...
(Haven't tried it with MySQL...)

Categories