如何允许EF4 CodeFirst数据库初始化程序在开发中运行,但不能在生产中运行

我正在尝试在线部署我的第一个alpha版系统,以便少数人开始使用。 在开发时,我大量使用DropCreateDatabaseOnModelChange (我现在没有它在我面前,所以我无法validation确切的名称)每次我的模型更改时重新初始化我的开发数据库。 这发生在Global.asax

但是,我不希望这种情况发生在我的网络主机上,其他人正在输入真实数据。 我需要自己处理所有数据库迁移,以便保留数据。

我曾考虑#ifdef DEBUG标签以防止调用数据库初始化程序,但我不喜欢这种解决方案。 现在,我已经部署了调试版本,所以如果他们遇到任何错误,我很容易看到并调试它们(这是非常非常的alpha,所以只有少数几个人正在使用它并知道预期错误)。

还有哪些其他选项可以防止Prod DB首先被EF4代码丢弃?

您始终可以创建新的配置(除了调试和发布)。 然后,您将为新配置定义条件编译符号。 例如,如果我创建了一个名为LocalDebug的新配置(在默认调试中具有相同的设置),那么我将LOCALDEBUG添加到条件编译符号中。 通过此定义,您可以使用:

 #if LOCALDEBUG //do database stuff #endif 

然后,您仍然可以部署内置的调试配置,此部分将不会触发。

怎么样控制反转:

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

根据您的IoC配置,您将返回开发或生产初始化程序。 您可以为每个构建配置配置不同的配置文件,这样您也可以对IoC容器进行不同的配置。

 public class ThrowExceptionInitializer : IDatabaseInitializer { public InitializeDatabase(Context context) { // Custom exception throw new InvalidVersionException("The new application version is not supported by the database version"); } } 

正如@Johann所说, ConditionalAttribute可能是这里的清除解决方案:

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

在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(); } 

您可以使用Conditional属性,但它与#ifdef没有太大区别

如果您在开发中使用sql express而不是在生产盒上,则可以通过连接进行过滤。

 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()); } } }