How do I allow the EF4 CodeFirst database initiali

2019-02-07 12:54发布

I am attempting to deploy my first alpha version of a system online for a few people to start using. On development I make heavy use of the DropCreateDatabaseOnModelChange<TContext> (I don't have it in front of me at the moment so I can't verify the exact name) to re-initialize my dev database every time my model changes. This happens in the Global.asax.

However, I do not want this to happen on my web host where other people are entering real data. I need to handle all db migrations on there myself so data is preserved.

I had considered #ifdef DEBUG tags to prevent the database initializer from being called, but I don't like that solution. Right now, I have the debug version deployed, so if they come across any errors it is easy for me to see and debug them (this is very very alpha, so only a select few people are using it and know to expect errors).

What other options do I have to prevent Prod DB dropping by EF4 code first?

5条回答
放荡不羁爱自由
2楼-- · 2019-02-07 13:29

You can always create a new Configuration (in addition to Debug and Release). You would then define a Conditional Compilation Symbol for the new configuration. For example if I created a new configuration called LocalDebug (with the same settings at the default debug) I would then add LOCALDEBUG to the Conditional Compilation Symbols. With this defined you can use:

#if LOCALDEBUG
  //do database stuff
#endif

Then you can still deploy the built in debug configuration and this section will not fire.

查看更多
ら.Afraid
3楼-- · 2019-02-07 13:34

If you are using sql express in development and not on your production box you can filter by the connection.

protected void Application_Start(object sender, EventArgs e)
{
  using (var db = new MyDb())
  {
    if (db.Database.Connection.DataSource.IndexOf("sqlexpress", StringComparison.InvariantCultureIgnoreCase) > -1)
    {
        Database.SetInitializer(new MyDbInitializer());
    }
  }
}
查看更多
混吃等死
4楼-- · 2019-02-07 13:36

You could use the Conditional attribute but it is not so different from the #ifdef

查看更多
爱情/是我丢掉的垃圾
5楼-- · 2019-02-07 13:42

As @Johann says, the ConditionalAttribute is probably the cleanes solution here:

[Conditional("DEBUG")]
private void InitializeDb()
{
    // Initializer code here
    // DropCreateDatabaseOnModelChange<TContext>
}

and in Global.asax:

public void Application_Start // or wherever it is you're initializing
{
    // This will only be called if the DEBUG constant is defined
    InitializeDb();
}
查看更多
smile是对你的礼貌
6楼-- · 2019-02-07 13:55

What about inversion of control:

var initializer = container.Resolve<IDatabaseInitializer<Context>>();
Database.SetInitializer(initializer);

Based on your IoC configuration you will either return developement or production initializer. You can have different configuration file for each build configuration so you can also have IoC container configured differently.

public class ThrowExceptionInitializer : IDatabaseInitializer<Context>
{
    public InitializeDatabase(Context context)
    {
        // Custom exception
        throw new InvalidVersionException("The new application version is not supported by the database version");
    }
}
查看更多
登录 后发表回答