Принудительно использовать код для инициализации несуществующей базы данных? - программирование
Подтвердить что ты не робот

Принудительно использовать код для инициализации несуществующей базы данных?

Иногда я удаляю свою базу данных разработки и запускаю свое приложение с первым кодом EF. Я получу ошибку:

Невозможно открыть базу данных "Система оценки", запрошенная логином. Ошибка входа в систему. Ошибка входа для пользователя "ОценкаAdmin".

Я думаю, это связано с тем, что DbContext запускает логику инициализации DB "один раз в AppDomain, когда контекст используется в первый раз", поскольку this страница. Это означает, что мне нужно переработать пул приложений IIS, чтобы получить EF для воссоздания моей базы данных, если я его опустил.

Есть ли способ получить код инициализации DB для запуска каждый раз при попытке получить доступ к базе данных? Таким образом, он всегда проверяет, существует ли база данных, а если нет, создайте ее, а не пытайтесь ее открыть, даже если она использует тот же AppDomain, который ранее обращался к базе данных, которую я сейчас потерял?

Обратите внимание, что я хотел бы, чтобы эта проверка инициализации выполнялась для каждого запроса, поэтому даже сделать это в Application_Start не достаточно часто; в идеале, я хотел бы иметь возможность загружать некоторые данные БД, удалять БД, затем загружать некоторые данные БД, и он воссоздает БД, даже если мне даже не придется перезагружать приложение (в основном мне просто нужно перезагрузить веб-страницу, загружает некоторые данные БД).

4b9b3361

Ответ 1

Инициализатор выполняется, когда вам нужно получить доступ к базе данных, поэтому, если вы хотите создать базу данных при запуске приложения, используйте что-нибудь из следующего:

    context.Database.Initialize(true); //If set to true the initializer is run even if it has already been run.       
    context.Database.Create()

http://msdn.microsoft.com/en-us/library/system.data.entity.database.initialize(v=vs.103).aspx

CreateDatabaseIfNotExists Реализация IDatabaseInitializer, которая будет воссоздать и, возможно, повторно засеять базу данных с данными, только если база данных не существует. Чтобы засеять базу данных, создайте производный класс и переопределите метод Seed.

Database.SetInitializer<MyContext>(new CreateDatabaseIfNotExists<MyContext>());

http://msdn.microsoft.com/en-us/library/gg679221(v=vs.103).aspx

DropCreateDatabaseIfModelChanges Реализация IDatabaseInitializer, которая будет удалять, воссоздавать и, возможно, повторно загружать базу данных с данными, только если модель изменилась с момента создания базы данных. Это достигается путем записи хэша модели хранилища в базу данных при ее создании, а затем сравнения этого хэша с одним, сгенерированным из текущей модели. Чтобы засеять базу данных, создайте производный класс и переопределите метод Seed.

Стратегия инициализации может дополнительно проверять наличие базы данных существование, создать новую базу данных и засеять базу данных данными. стратегия по умолчанию - это пример CreateDatabaseIfNotExists.

Database.SetInitializer(новый DropCreateDatabaseIfModelChanges());

Обратите внимание, что это предполагает, что у вас есть разрешение даже отказаться от базы данных.

http://msdn.microsoft.com/en-us/library/gg679604(v=vs.103).aspx

DropCreateDatabaseAlways

Реализация IDatabaseInitializer, которая всегда будет воссоздавать и, возможно, повторно загружать базу данных с данными при первом использовании контекста в домене приложения. Чтобы засеять базу данных, создайте производный класс и переопределите метод Seed.

Database.SetInitializer<MyContext>(new DropCreateDatabaseAlways<MyContext>());

http://msdn.microsoft.com/en-us/library/gg679506(v=vs.103).aspx

Я рекомендую вам посмотреть Миграции, если вы хотите отслеживать, вернуть изменения, внесенные в вашу БД, в предыдущее состояние http://msdn.microsoft.com/hr-hr/data/jj591621.

UPDATE

context.Database.Initialize(true);

Если для параметра force установлено значение true, выполняется инициализатор независимо от того, был ли он запущен раньше. Это может быть полезно, если база данных удаляется во время работы приложения и должна быть повторно инициализированным.

Для приложения MVC добавьте раздел в метод Application_Start() в Global.asax

protected void Application_Start() {

     Database.SetInitializer<MyContext>(new DropCreateDatabaseAlways<MyContext>()); 

     // Forces initialization of database on model changes.
     using (var context= new MyContext()) {
          context.Database.Initialize(force: true);
     }    
}

Также вы можете использовать пользовательский инициализатор:

public class MyDbInit : DropCreateDatabaseAlways<MyContext>
{

}

а затем используйте

Database.SetInitializer(new MyDbInit());

ОБНОВЛЕНИЕ 2

Сделайте новое пустое приложение MVC4 с именем DeleteDBOnEveryRequest. Поместите в Global.asax Application_start следующее:

protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);

            Database.SetInitializer<BlogContext>(new DropCreateDatabaseAlways<BlogContext>());    

            using (var context = new BlogContext())
            {
                context.Database.Initialize(force: true);
            }    
        }

Создайте новый контроллер с именем DatabaseController с двумя действиями.

В действии Доступ вы удаляете БД и перенаправляете на действие Восстановленное, из которого вы создаете БД, поскольку он был ранее удален.

namespace DeleteDBOnEveryRequest.Controllers
{
    public class DatabaseController : Controller
    {
        public ActionResult Access()
        {
            using (var context = new BlogContext())
            {
                context.Database.Delete();
            } 
            return RedirectToAction("Recreated");
        }

        public ActionResult Recreated()
        {
            using (var context = new BlogContext())
            {
                context.Database.Initialize(force: true);                
            }
            return View();
        }
    }
}

Это то, что вы хотели?