Как разрешить инициализатор базы данных EF4 CodeFirst запускаться под разработку, но не запускаться в процессе производства

Я пытаюсь развернуть свою первую альфа-версию системы онлайн для нескольких человек, чтобы начать использовать. При разработке я активно использую DropCreateDatabaseOnModelChange<TContext> (у меня его нет на данный момент, поэтому я не могу проверить точное имя), чтобы повторно инициализировать мою базу данных dev каждый раз, когда меняет модель. Это происходит в Global.asax.

Однако я не хочу, чтобы это происходило на моем веб-хосте, где другие люди вводят реальные данные. Мне нужно обрабатывать все миграции db там, поэтому данные сохраняются.

Я рассмотрел теги #ifdef DEBUG, чтобы предотвратить вызывать инициализатор базы данных, но мне не нравится это решение. Прямо сейчас, у меня версия отладки развернута, поэтому, если они сталкиваются с любыми ошибками, мне легко увидеть и отладить их (это очень альфа, поэтому только немногие используют его и знают, что ожидать ошибок).

Какие еще параметры я должен предотвратить, прежде всего, для того, чтобы предотвратить падение кода программы с помощью кода EF4?

Ответ 1

Вы всегда можете создать новую конфигурацию (в дополнение к Debug и Release). Затем вы определяете условный символ компиляции для новой конфигурации. Например, если я создал новую конфигурацию под названием LocalDebug (с теми же настройками при отладке по умолчанию), я бы добавил LOCALDEBUG в условные символы компиляции. С помощью этого определения вы можете использовать:

#if LOCALDEBUG
  //do database stuff
#endif

Затем вы можете развернуть встроенную конфигурацию отладки, и этот раздел не будет срабатывать.

Ответ 2

Как насчет инверсии управления:

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

На основе вашей конфигурации IoC вы либо вернетесь к разработке или инициализации производства. У вас может быть другой файл конфигурации для каждой конфигурации сборки, поэтому вы также можете настроить контейнер IoC по-разному.

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

Ответ 3

Как говорит @Johann, ConditionalAttribute, вероятно, является решением для очистки здесь:

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

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

Ответ 4

Вы можете использовать атрибут Conditional, но он не так сильно отличается от #ifdef

Ответ 5

Если вы используете 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());
    }
  }
}