Подтвердить что ты не робот

Исключение, когда код сначала попытался создать базу данных

Я создал новое приложение ASP.NET MVC 4 и хотел бы, чтобы он сначала использовал код. Однако, по-видимому, он не создает исходный файл базы данных, если он уже не существует. Если я удалю файл .mdf из папки App_Data, я получаю следующее исключение, когда приложение пытается получить доступ к базе данных:

System.Data.SqlClient.SqlException: Cannot attach the file '<path-to-db-file>.mdf' as database '<my-db-file-name>'.

Если я запустил его в приложении в отладчике, я вижу, что это исключение происходит в методе InitializeSimpleMembershipAttribute:: OnActionExecuting при вызове LazyInitializer.EnsureInitialized. Исключенное исключение:

[System.Reflection.TargetInvocationException]   {"Exception has been thrown by the target of an invocation."}   System.Reflection.TargetInvocationException

С внутренним исключением:

[System.InvalidOperationException]  {"The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588"} System.InvalidOperationException

Который имеет первое исключение, упомянутое выше как внутреннее исключение.

Любые идеи, что я делаю неправильно?

Обновление

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

  • Создайте приложение MVC в мастере VS.
  • Запустите приложение в первый раз и перейдите на страницу входа (обратите внимание, что файл mdf теперь генерируется).
  • Удалите файл mdf и вернитесь на страницу входа в систему. Исключение теперь выбрано.
4b9b3361

Ответ 1

Попал в ту же проблему и нашел мое решение здесь. все, что вам нужно сделать, это остановить LocalDb, открыв командную строку разработчика VS и введите (без кавычек):

"sqllocaldb.exe stop v11.0"

"sqllocaldb.exe удалить v11.0"

В следующий раз EF будет регенерировать файл, а также db.

Ответ 2

Если вы вникнете в свой класс InitializeSimpleMembershipAttribute вашего приложения, вы увидите следующий переопределенный метод класса ActionFilterAttribute, из которого он наследует:

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // Ensure ASP.NET Simple Membership is initialized only once per app start
        LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
    }

Обратите внимание, что комментарий. Приложение проверяет один раз за запуск, чтобы убедиться, что Simple Membership была правильно инициализирована. Посмотрите на частные переменные в верхней части класса:

    private static SimpleMembershipInitializer _initializer;
    private static object _initializerLock = new object();
    private static bool _isInitialized;

Все они статичны, и все они передаются как ref. Важный здесь для вашей ситуации - _isInitialized. То, что LazyInitializer.EnsureInitialized делает, проверяет флаг _isInitialized, и если он является ложным, он инициализирует переданную им цель ref, в данном случае _initializer типа SimpleMembershipInitializer. В этот момент он устанавливает флаг в true и переходит. Если LazyInitializer.EnsureInitialized видит, что флаг true, он ничего не возвращает, а возвращает цель. Поскольку этот флаг является статической переменной, он сохраняет свою ценность для жизни приложения, что означает, что после этой первой инициализации EnsureInitialized всегда будет просто возвращать цель, даже если файл базы данных больше не существует. Другими словами, если вы удалите файл .mdf после инициализации, приложение не будет знать, и исключения будут выбрасываться, когда приложение попытается прочитать или записать из базы данных. Чтобы решить эту проблему, вам необходимо перезапустить приложение, что означает убийство сервера dev, если это то, что вы используете или перезапускаете приложение в IIS.

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

CREATE FILE обнаружила ошибку операционной системы 5 (доступ запрещен.) при попытке открыть или создать физический файл 'C:\path\to\your\project\App_Data\dbfile.mdf'. CREATE DATABASE не удалось. Некоторые имена файлов не могут быть созданы. Проверьте связанные ошибки.

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

По умолчанию Visual Studio 2012 использует уменьшенную версию SQL Server Express под названием LocalDB. LocalDB будет разворачивать дочерний процесс приложения, и если вы запускаете свое приложение на сервере разработки Visual Studio (например, http://localhost: [порт] - это то, что отображается в вашем браузере), то вы запускаете оба приложения и LocalDB под учетной записью пользователя, а не под SYSTEM или NETWORKSERVICE. Все, что вам нужно сделать, чтобы исправить это, - это назначить для пользователя права на изменение прав доступа к папке App_Data вашего проекта. Повторите попытку входа и файл .mdf должен быть создан успешно.

Если вам интересно, вы можете узнать больше о LocalDB здесь.

Ответ 3

Вы можете обрабатывать инициализацию базы данных Code First в методе Application_Start файла Global.asax в корневой папке вашего проекта, например:

    protected void Application_Start()
    {
        Database.SetInitializer<MyDBContext>(null);
    }

Если вы передадите null в SetInitializer, он не будет создавать или изменять таблицы базы данных, вы должны сделать это вручную.

Причина, по которой база данных не создается повторно, заключается в том, что Application_Start запускается только один раз в течение срока службы приложения.

Ответ 4

Сгенерированный MVC код работает со строкой подключения базы данных с именем "DefaultConnection". Если вы использовали другое имя в Web.config, вам нужно обратиться к этому имени в:

  • InitializeSimpleMembershipAttribute.SimpleMembershipInitializer.ctor() в InitializeSimpleMembershipAttribute.cs).
  • UsersContext.ctor() в AccountModel.cs

(или просто выполните поиск "DefaultConnection" в вашем проекте).

Ответ 5

Вы никогда не должны удалять автообновленные файлы .mdf в проводнике только с помощью инструментов управления SQL или в обозревателе объектов.

Проблема, которую вы получаете (и можете реплицировать в шагах, которые вы указали), заключается в том, что база данных все еще зарегистрирована в LocalDb.

Ответ 6

Вам нужно остановить экземпляр IISExpress и снова перезапустить его (нажав F5 в Visual Studio). Затем вы сможете снова создать базу данных.

Ответ 7

то, что исправлено для меня, когда я получал эту ошибку, заключается в том, что я изменил строку подключения в файле App.config моего проекта VS.

Я добавил это в строку подключения:

  <connectionStrings>
<add name="Blog" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Integrated Security=true;AttachDbFileName=C:\Users\kostadin\Database1.mdf" providerName="System.Data.SqlClient" />

Надеюсь, это поможет кому-то еще.