ReSeed database in Azure - c#

I have this inicializer in my project:
public class MyInitializer : CreateDatabaseIfNotExists<AppDbContext>
I have also deployed an application in Azure with SQL database.
I would like to clear the whole DB and reseed it with my initializer. How can I do it please?

You can create your custom initializer
public class MyCustomInitializer : IDatabaseInitializer<AppDbContext>
{
public void InitializeDatabase(AppDbContext context)
{
if (context.Database.Exists())
{
context.Database.Delete();
}
context.Database.Create();
// populate data
}
}

I found out that the only possible option is to manually delete my DB, then create new DB with same name (so the same connection string) and that's it.

Related

Change DB name for Entity Framework DbContext

I have inherited an application which is using Entity Framework to access a SQL Server database. The DbContext class has the constructor as shown below, where BuildingPermits is the name of the initial catalog.
I would like to be able to switch between databases (with the same connection) via a config file instead of changing the code.
How can I accomplish this?
public BuildingPermitsDbContext() : base("BuildingPermits")
{
Database.SetInitializer<BuildingPermitsDbContext>(null);
}
You can try this.
using System.Configuration;
public BuildingPermitsDbContext() : base(DatabaseName())
{
Database.SetInitializer<BuildingPermitsDbContext>(null);
}
private static string DatabaseName()
{
var db = ConfigurationManager.AppSettingss["desiredDbName"];
return db;
}

EF6 change database create strategy

I have an application where I want to use the FILESTREAM feature for storing blobs. I know that EF6 does not support FILESTREAM, so I will manage file and image handling by myself. However, I have to write my own initialize code to add a FILEGROUP and FILE to my Database and:
public class CustomDbInitializer : CreateDatabaseIfNotExists<DatenbankContext>
{
public override void InitializeDatabase(DatenbankContext context)
{
base.InitializeDatabase(context);
SqlConnectionStringBuilder b = new SqlConnectionStringBuilder(context.Database.Connection.ConnectionString);
context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction,"ALTER DATABASE "+ b.InitialCatalog + " ADD FILEGROUP GRP CONTAINS FILESTREAM");
//more sql commands
}
}
Then, I call manually the function InitializeDatabase(context)
new CustomDbInitializer().InitializeDatabase(context);
However, I find this a bit clunky and counter-intuitive. I know that I can set an initializer for the context in the constructor, but this does not work the way I want:
public class DatenbankContext : DbContext
{
public DatenbankContext()
:base("name=name")
{
Database.SetInitializer(new CustomDbInitializer());
}
}
Basically, I want the call
new DatenbankContext() // or
context.Database.CreateIfNotExists()
to initialize my Database with my custom strategy in an intuitive way. How can this be done?
Inside your custom initializer add:
if (!context.Database.Exists())
{
context.Database.Create();
}
// Do next steps
Call your initializer inside a static constructor. This insures it only runs once:
public class DatenbankContext : DbContext
{
static DatenbankContext()
{
Database.SetInitializer(new CustomDbInitializer());
}
}
See here for more on custom initializers. You probably don't want to inherit from CreateDatabaseIfNotExists if you want control over the process. See the example in link.

seed data from one database to other database when application start to run mvc

i have to database one is realy database and second database to testing i need the realy data for testing
i want always the solution is run to copy the real data to the testing database
using mvc c#
i think i need code like this
protected void Application_Start()
{
Database.SetInitializer<LocatorContext>(new DropCreateDatabaseAlways<LocatorContext>());
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
To seed data into your database, you have to create custom database initializer,and override the Seed method.
The following example shows how you can provide default data from another database or another SQL server.
You can also use context.Database.SqlQuery to handle/update the data in C# Seed method and then push the changes back to the Sql Server/database.
public class SeedDbInitializer : DropCreateDatabaseAlways<MyDbContext>
{
protected override void Seed(MyDbContext context)
{
context.Database.ExecuteSqlCommand(
#"SELECT * INTO targetTable
FROM[sourceserver].[sourcedatabase].[dbo].[sourceTable]"
);
base.Seed(context);
}
}
public class MyDbContext : DbContext
{
public MyDbContext() : base("MyConnectionString")
{
Database.SetInitializer<MyDbContext>(new SeedDbInitializer());
}
public DbSet<User> Users { get; set; }
}

How to create initializer to create and migrate mysql database?

I have been learning how to use EF for a week or so now and am stuck on the issue of creating/updating my database. I am able to create an initializer to create the database if it is not there:
static class Program
{
static void Main()
{
Database.SetInitializer<GumpDatabase>(new GumpDatabaseInitializer());
....
class GumpDatabaseInitializer : CreateDatabaseIfNotExists<GumpDatabase>
{
public GumpDatabaseInitializer()
{
}
protected override void Seed(GumpDatabase context)
{
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Stations (Name)");
// Other stuff
}
}
Or I can create a Configuration to migrate the db
static class Program
{
static void Main()
{
Database.SetInitializer<GumpDatabase>(new MigrateDatabaseToLatestVersion<GumpDatabase, Configuration>());
....
internal sealed class Configuration : DbMigrationsConfiguration<GumpDatabase>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());
}
protected override void Seed(GumpDatabase context)
{
}
Each works correctly but I haven't figured out a way to do both. I can switch between the two initializers by changing the SetInitializer call but if I want to create the database if it is not there and also migrate it if it is what do I do? Do I need to create a custom initializer?
Thanks
Edit based on NSGaga answer
class CreateOrMigrateDatabaseInitializer<TContext, TConfiguration> : CreateDatabaseIfNotExists<TContext>, IDatabaseInitializer<TContext>
where TContext : DbContext
where TConfiguration : DbMigrationsConfiguration<TContext>, new()
{
private readonly DbMigrationsConfiguration _configuration;
public CreateOrMigrateDatabaseInitializer()
{
_configuration = new TConfiguration();
}
public CreateOrMigrateDatabaseInitializer(string connection)
{
Contract.Requires(!string.IsNullOrEmpty(connection), "connection");
_configuration = new TConfiguration
{
TargetDatabase = new DbConnectionInfo(connection)
};
}
void IDatabaseInitializer<TContext>.InitializeDatabase(TContext context)
{
Contract.Requires(context != null, "context");
if (context.Database.Exists())
{
if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false))
{
var migrator = new DbMigrator(_configuration);
migrator.Update();
}
}
else
{
context.Database.Create();
Seed(context);
context.SaveChanges();
}
}
protected virtual void Seed(TContext context)
{
}
}
and
internal sealed class Configuration : DbMigrationsConfiguration<GumpDatabase>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = false;
SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());
}
protected override void Seed(GumpDatabase context)
{
}
}
and
class GumpDatabaseInitializer : CreateOrMigrateDatabaseInitializer<GumpDatabase,Gump.Migrations.Configuration>
{
public GumpDatabaseInitializer()
{
}
protected override void Seed(GumpDatabase context)
{
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Stations (Name)");
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Sequences (Name)");
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX StationPartNumber ON StationPartNumbers (StationId,PartNumberId)");
}
}
and finally
static void Main()
{
Database.SetInitializer<GumpDatabase>(new GumpDatabaseInitializer());
I think you're pretty much there - you can lookup the source code for MigrateDatabaseToLatestVersion (it's open source http://entityframework.codeplex.com/) - it's pretty simplistic, what it does pretty much is call the DbMigrator - as far as I could see.
All you have to do seems is to merge the two - use one or the other as a basis, add other functionality in there - that should work fine I think.
class CreateAndMigrateDatabaseInitializer<TContext, TConfiguration> : CreateDatabaseIfNotExists<TContext>, IDatabaseInitializer<TContext>
where TContext : DbContext
where TConfiguration : DbMigrationsConfiguration<TContext>, new()
{
private readonly DbMigrationsConfiguration _configuration;
public CreateAndMigrateDatabaseInitializer()
{
_configuration = new TConfiguration();
}
public CreateAndMigrateDatabaseInitializer(string connection)
{
Contract.Requires(!string.IsNullOrEmpty(connection), "connection");
_configuration = new TConfiguration
{
TargetDatabase = new DbConnectionInfo(connection)
};
}
void IDatabaseInitializer<TContext>.InitializeDatabase(TContext context)
{
Contract.Requires(context != null, "context");
var migrator = new DbMigrator(_configuration);
migrator.Update();
// move on with the 'CreateDatabaseIfNotExists' for the 'Seed'
base.InitializeDatabase(context);
}
protected override void Seed(TContext context)
{
}
}
call it like this...
Database.SetInitializer(new CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>());
...actually, override it (since it's generic implementation) like you were doing for CreateDatabaseIfNotExists (you just have extra 'param' for Configuration) - and just supply the 'Seed'.
class GumpDatabaseInitializer : CreateAndMigrateDatabaseInitializer<GumpDatabase, YourNamespace.Migrations.Configuration>
{
protected override void Seed(GumpDatabase context)
{
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX Name ON Stations (Name)");
}
}
...and call it something like
Database.SetInitializer(new GumpDatabaseInitializer());
EDIT:
Based on the comments - DbMigrator should not run twice. It always checks (spends a bit of time) and does a 'blank' update and moves on. However just in case if you'd like to remove that and 'check' before entering - this should work (change the similar piece above)...
var migrator = new DbMigrator(_configuration);
if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false))
if (migrator.GetPendingMigrations().Any())
migrator.Update();
(this is a redundant / double-check - one of the if-s should be enough. Put a break there - and see exactly what's happening, it should not get in - once Db is migrated. As I mentioned, works fine when I test it.
EDIT:
Replace the inside of InitializeDatabase with...
var doseed = !context.Database.Exists();
// && new DatabaseTableChecker().AnyModelTableExists(context);
// check to see if to seed - we 'lack' the 'AnyModelTableExists' - could be copied/done otherwise if needed...
var migrator = new DbMigrator(_configuration);
// if (doseed || !context.Database.CompatibleWithModel(throwIfNoMetadata: false))
if (migrator.GetPendingMigrations().Any())
migrator.Update();
// move on with the 'CreateDatabaseIfNotExists' for the 'Seed'
base.InitializeDatabase(context);
if (doseed)
{
Seed(context);
context.SaveChanges();
}
This works around (half-way) not-seeding - if migration goes first. And migrations have to be first, otherwise you have issues.
You still need to do it properly - this is the gist if not all you might need - but if any issues w/ MySQL etc., probably some more leg work here.
Note: Still seeding doesn't call if you have a db, but it's empty. Problem is mixing of the two different initializers. So you'll have to work that out - either by implementing what Create... does inside (that call we can't call) or something else.
Actually it should be:
var migrator = new DbMigrator(_configuration);
if (!context.Database.CompatibleWithModel(false) || migrator.GetPendingMigrations().Any())
migrator.Update();
because if we have a migration, that is not related to our db model, for example inserting a row in any of our tables, the migration won't be executed.
To do both (seed and migrate) you really only have to use migrations with a MigrateDatabaseToLatestVersion initializer. When you enable migrations for your context a Configuration class derived from DbMigrationsConfiguration is created and you can override the Seed method to seed your database. Note that the database may already contain seed data when this method executes but the AddOrUpdate extension method conveniently helps you make "upserts" in your database.
This is different compared to the Seed method of some of the other database intitializers where the database is only seeded when it is initially created. However, when you are using migrations you may want to change your seed data when the database changes and using MigrateDatabaseToLatestVersion makes that possible.
To combine seeding with migrations you will have to perform the following steps in a new project:
Create a code-first DbContext with associated entities
In the package manager console execute the command Enable-Migrations
In the Migrations folder a Configuration class is generated with a Seed method. You can modify this method to seed your database:
protected override void Seed(MyContext context) {
// Add two entities with name "Foo" and "Bar".
context.MyEntities.AddOrUpdate(
e => e.Name,
new MyEntity { Name = "Foo" },
new MyEntity { Name = "Bar" }
);
}
You need to create a database initializer that derives from MigrateDatabaseToLatestVersion:
class MyContextInitializer
: MigrateDatabaseToLatestVersion<MyContext, Migrations.Configuration> { }
You will also have to configure the initializer either by calling Database.SetInitializer(new MyContextInitializer()) when you application starts or in the App.config file by using the <databaseInitializer/> element.
In the constructor for the generated Configuration class you can enable automatic migrations:
public Configuration() {
AutomaticMigrationsEnabled = true
}
However, in a team you might prefer to not do that. In that case you will have to create an initial migration (unless it was created when you did Enable-Migrations). In the package manager execute the command Add-Migration InitialCreate. This creates the first migration required to create your database.
At this point you have a DbContext with migrations and a Seed method.
So to sum it: Enable migrations, use the MigrateDatabaseToLatestVersion initializer and add seed data in the Configuration class that was generated when migrations were enabled.
While MigrateDatabaseToLatestVersion does actually create the DB if it does not exist and even allows you to seed it, if you already have a working solution based on CreateDatabaseIfNotExists and/or don't want to complicate it with testing for existence of seed data, you can just use the below by inheriting from it rather than from CreateDatabaseIfNotExists:
public class CreateOrMigrateDatabaseInitializer<TContext, TConfiguration> : CreateDatabaseIfNotExists<TContext>, IDatabaseInitializer<TContext>
where TContext : DbContext
where TConfiguration : DbMigrationsConfiguration<TContext>, new()
{
void IDatabaseInitializer<TContext>.InitializeDatabase(TContext context)
{
if (context.Database.Exists())
{
if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false))
{
var migrationInitializer = new MigrateDatabaseToLatestVersion<TContext, TConfiguration>(true);
migrationInitializer.InitializeDatabase(context);
}
}
base.InitializeDatabase(context);
}
}
This is based on previous answers and OP's own solution. This should work with other providers as well, but I only tested with SQL Server.

ASP.net Entity Framework Code First custom initializer never called

I am using EF Code First in an Asp.net project. Code First created my database just fine but I am having fits getting it to seed my database with data. I am using a custom database initializer like so:
namespace Toolkit.Model
{
public class EntitiesContextInitializer : DropCreateDatabaseIfModelChanges<ToolkitContext>
{
protected override void Seed(ToolkitContext context)
{
List<Server> Servers = new List<Server>
{
new Server { ServerName = "Server 16" },
new Server { ServerName = "Server 29" }
};
foreach (Server server in Servers)
{
context.Servers.Add(server);
}
context.SaveChanges();
}
}
}
I set the initializer in the the Global.asax.cs and force the database to initialize like so:
using Toolkit.Model;
namespace Toolkit
{
public class Global : System.Web.HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
Database.SetInitializer(new EntitiesContextInitializer());
var context = new ToolkitContext();
context.Database.Initialize(false);
}
...
}
The problem is that my Initializer never gets called and so my database never gets populated. I have even tried changing the initializer to inherit DropCreateDatabaseAlways instead but still nothing... What am I missing here?
EDIT
So after dropping the database my initializer got called fine. However I still wonder why it didn't get called in other instances such as when I added a table (so the model changed) or when I changed the initialzer to be DropCreateDatabaseAlways.
I'm using a similar configuration for a SQL CE database, but instead of DropCreate, I'm using CreateIfNotExists.
The difference between what I have and yours is that you have are creating a context and calling initialize on the database. Based on that, I would suggest that you remove the context setup and the Database.initialize calls that you have in the application_start method.
try
Database.SetInitializer<MyContextName>(new EntitiesContextInitializer)
in EF 5.0 the library is declared as
public static void SetInitializer<TContext>(IDatabaseInitializer<TContext> strategy) where TContext : DbContext;
You can use Database Migrations with Code-First. Whenever you use Update-database command when your model changes, your Seed method (in Migrations) will be called.
This article explains more:
http://msdn.microsoft.com/en-gb/data/jj591621
You can also force it in Application_Start() your way:
Database.SetInitializer(new EntitiesContextInitializer());
var context = new ToolkitContext();
context.Database.Initialize(true);
At the end of your overriden menthod, Seed, in class, EntitiesContextInitializer, place at the end of the method add a line:
base.Seed (context)

Categories