Generating seed code from existing database in ASP.NET MVC
Another way of seeding data is to run it as sql in an Up migration.
I have code that will read a sql file and run it
using System;
using System.Data.Entity.Migrations;
using System.IO;
public partial class InsertStandingData : DbMigration
{
public override void Up()
{
var baseDir = AppDomain.CurrentDomain
.BaseDirectory
.Replace("\\bin", string.Empty) + "\\Data\\Sql Scripts";
Sql(File.ReadAllText(baseDir + "\\StandingData.sql"));
}
public override void Down()
{
//Add delete sql here
}
}
So if your ETL generates sql for you then you could use that technique.
The advantages of doing it in the Up method are
- It will be quicker than doing it using
AddOrUpdate
becauseAddOrUpdate
queries the database each time it is called to get any
already existing entity. - You are normally going from a known state (e.g. empty tables) so you probably
don't need to check whether data exists already. NB to ensure this
then you should delete the data in theDown
method so that you can
tear all the way down and back up again. - The Up method does not run every time the application starts.
The Seed method provides convenience - and it has the advantage (!?) that it runs every time the application starts
But if you prefer to run the sql from there use ExecuteSqlCommand
instead of Sql
:
string baseDir = AppDomain.CurrentDomain.BaseDirectory.Replace("\\bin", string.Empty)
+ "\\Data\\Sql Scripts";
string path = Path.Combine(baseDir, "StandingData");
foreach (string file in Directory.GetFiles(path, "*.sql"))
{
context.Database.ExecuteSqlCommand(File.ReadAllText(file));
}
References:
Best way to incrementally seed data
Preparing for database deployment
Database Initializer and Migrations Seed Methods
MVC 5 Seed Users and Roles
Here is example of usual Seed approach:
protected override void Seed(SecurityModule.DataContexts.IdentityDb context)
{
if (!context.Roles.Any(r => r.Name == "AppAdmin"))
{
var store = new RoleStore<IdentityRole>(context);
var manager = new RoleManager<IdentityRole>(store);
var role = new IdentityRole { Name = "AppAdmin" };
manager.Create(role);
}
if (!context.Users.Any(u => u.UserName == "founder"))
{
var store = new UserStore<ApplicationUser>(context);
var manager = new UserManager<ApplicationUser>(store);
var user = new ApplicationUser {UserName = "founder"};
manager.Create(user, "ChangeItAsap!");
manager.AddToRole(user.Id, "AppAdmin");
}
}
I used package-manager "update-database". DB and all tables were created and seeded with data.
How can I get my database to seed using Entity Framework CodeFirst?
This is what my DbContext classes all look like and they seed just fine:
public class MyDbContext : DbContext
{
public DbSet<MyClass> MyClasses { get; set; }
protected override void OnModelCreating (DbModelBuilder modelBuilder)
{
base.OnModelCreating (modelBuilder);
modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention> ();
// Add any configuration or mapping stuff here
}
public void Seed (MyDbContext Context)
{
#if DEBUG
// Create my debug (testing) objects here
var TestMyClass = new MyClass () { ... };
Context.MyClasses.Add (TestMyClass);
#endif
// Normal seeding goes here
Context.SaveChanges ();
}
public class DropCreateIfChangeInitializer : DropCreateDatabaseIfModelChanges<MyDbContext>
{
protected override void Seed (MyDbContext context)
{
context.Seed (context);
base.Seed (context);
}
}
public class CreateInitializer : CreateDatabaseIfNotExists<MyDbContext>
{
protected override void Seed (MyDbContext context)
{
context.Seed (context);
base.Seed (context);
}
}
static MyDbContext ()
{
#if DEBUG
Database.SetInitializer<MyDbContext> (new DropCreateIfChangeInitializer ());
#else
Database.SetInitializer<MyDbContext> (new CreateInitializer ());
#endif
}
}
I have used this pattern a few times and it has worked out very well for me.
How to seed data when using Model First approach?
You can have something like this:
public class MySeedData : DropCreateDatabaseIfModelChanges<YourDataBaseContextClass>
{
protected override void Seed(YourDataBaseContextClass context)
{
// Create objects here and add them to your context DBSets...
}
}
public class YourDataBaseContextClass : DbContext
{
}
Then, within Application_Start()
you call:
Database.SetInitializer(new MySeedData());
In your case, you could try creating DbSets (using your model first classes) manually and try to plug it using the code above. It's kind of a mix of Model First + Code First.
public class FourthCoffeeWebContext : DbContext
{
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
}
Adding to this: CreateDatabaseIfNotExists<(Of <(<'TContext>)>)>
EF Code First Generate C# Seed Method from Database
In the package management console, enter the following command:
enable-migrations
It will enable the configuration part of EF and includes a Seed
method. If this is not enough there are more options you can explore, like add-migration
to add a custom migration.
See this post for details:
http://msdn.microsoft.com/en-us/data/jj554735.aspx or
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/migrations-and-deployment-with-the-entity-framework-in-an-asp-net-mvc-application
When using a Code Based Migration
, you can query for data, remove it and re-insert it any way you like.
Related Topics
How to Substitute a Left Join in Sql
Counter_Cache Has_Many_Through SQL Optimisation, Reduce Number of SQL Queries
Insert and Update a Record Using Cursors in Oracle
T-Sql Stop or Abort Command in SQL Server
Joining Two Separate Queries in a Postgresql ...Query... (Possible or Not Possible)
What Can Happen as a Result of Using (Nolock) on Every Select in SQL Server
Formatting Clear and Readable SQL Queries
Ruby on Rails Where Query with Nesting Relations
Query SQL Server Database from Native iOS Application
How to Use "Partition By" or "Max"
What Is The Purpose of Rowlock on Delete and When Should I Use It
Pl/Sql- Get Column Names from a Query