"Невозможно удалить базу данных, потому что она в настоящее время используется". Как это исправить?
имея этот простой код, я получаю "не могу удалить базу данных "test_db", потому что она в настоящее время используется" (метод очистки), когда я ее запускаю.
[TestFixture]
public class ClientRepositoryTest
{
private const string CONNECTION_STRING = "Data Source=.;Initial Catalog=test_db;Trusted_Connection=True";
private DataContext _dataCntx;
[SetUp]
public void Init()
{
Database.SetInitializer(new DropCreateDatabaseAlways<DataContext>());
_dataCntx = new DataContext(CONNECTION_STRING);
_dataCntx.Database.Initialize(true);
}
[TearDown]
public void CleanUp()
{
_dataCntx.Dispose();
Database.Delete(CONNECTION_STRING);
}
}
DataContext имеет одно свойство, как это
public DbSet<Client> Clients { get; set; }
Как заставить мой код удалить базу данных?
Спасибо
7 ответов:
проблема в том, что ваше приложение, вероятно, все еще имеет некоторое соединение с базой данных (или другое приложение также имеет соединение). База данных не может быть удалена при наличии любого другого открытого соединения. Первая проблема, вероятно, может быть решена путем отключения пула соединений (add
Pooling=falseв строку подключения) или очистить пул перед удалением базы данных (путем вызоваSqlConnection.ClearAllPools()).обе проблемы могут быть решены путем принудительного удаления базы данных, но для этого вам нужен пользовательский инициализатор базы данных, где вы переключаете базу данных в однопользовательский режим и после этого удаляете ее. здесь это какой-то пример, как этого добиться.
Я сходил с ума от этого! У меня есть открытое соединение с базой данных внутри
SQL Server Management Studio (SSMS)и табличный запрос, открытый для просмотра результатов некоторых модульных тестов. При повторном запуске тестов внутри Visual Studio я хочу, чтобы онdropбаза данных ДАЖЕ ЕСЛИ соединение открыто в SSMS.вот окончательный способ избавиться от
Cannot drop database because it is currently in use:Инициализация Базы Данных Entity Framework
фокус в том, чтобы переопределить
InitializeDatabaseметод внутри customInitializer.скопировал соответствующую часть здесь ради
goodдублирование... :)если база данных уже существует, вы можете наткнуться на случай наличия ошибка. Исключение " не удается удалить базу данных, потому что она в настоящее время в использовании " может поднять. Эта проблема возникает при активном подключении остается подключенным к базе данных, это в процессе удаленный. Хитрость заключается в переопределите метод InitializeDatabase и измените базу данных. Это говорит базе данных, чтобы закрыть все соединения и если транзакция открыта для отката этого.
public class CustomInitializer<T> : DropCreateDatabaseAlways<YourContext> { public override void InitializeDatabase(YourContext context) { context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction , string.Format("ALTER DATABASE [{0}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE", context.Database.Connection.Database)); base.InitializeDatabase(context); } protected override void Seed(YourContext context) { // Seed code goes here... base.Seed(context); } }
Это действительно агрессивный инициализатор базы данных (re) для EF code-first с миграциями; используйте его на свой страх и риск, но он, похоже, работает довольно повторяемо для меня. Это будет;
- принудительно отключите все другие клиенты от БД
- удалить БД.
- перестроить БД с миграциями и запускает метод Seed
- принять возрастов! (следите за ограничением времени ожидания для вашей тестовой платформы; по умолчанию 60-секундный тайм-аут может не быть хватит)
вот класс;
public class DropCreateAndMigrateDatabaseInitializer<TContext, TMigrationsConfiguration>: IDatabaseInitializer<TContext> where TContext: DbContext where TMigrationsConfiguration : System.Data.Entity.Migrations.DbMigrationsConfiguration<TContext>, new() { public void InitializeDatabase(TContext context) { if (context.Database.Exists()) { // set the database to SINGLE_USER so it can be dropped context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, "ALTER DATABASE [" + context.Database.Connection.Database + "] SET SINGLE_USER WITH ROLLBACK IMMEDIATE"); // drop the database context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, "USE master DROP DATABASE [" + context.Database.Connection.Database + "]"); } var migrator = new MigrateDatabaseToLatestVersion<TContext, TMigrationsConfiguration>(); migrator.InitializeDatabase(context); } }используйте его вот так;
public static void ResetDb() { // rebuild the database Console.WriteLine("Rebuilding the test database"); var initializer = new DropCreateAndMigrateDatabaseInitializer<MyContext, MyEfProject.Migrations.Configuration>(); Database.SetInitializer<MyContext>initializer); using (var ctx = new MyContext()) { ctx.Database.Initialize(force: true); } }Я также использую трюк Ladislav Mrnka 'Pooling=false', но я не уверен, требуется ли это или просто мера ремня и скоб. Это, безусловно, будет способствовать замедлению теста больше.
ни одно из этих решений работал для меня. Я закончил писать метод расширения, который работает:
private static void KillConnectionsToTheDatabase(this Database database) { var databaseName = database.Connection.Database; const string sqlFormat = @" USE master; DECLARE @databaseName VARCHAR(50); SET @databaseName = '{0}'; declare @kill varchar(8000) = ''; select @kill=@kill+'kill '+convert(varchar(5),spid)+';' from master..sysprocesses where dbid=db_id(@databaseName); exec (@kill);"; var sql = string.Format(sqlFormat, databaseName); using (var command = database.Connection.CreateCommand()) { command.CommandText = sql; command.CommandType = CommandType.Text; command.Connection.Open(); command.ExecuteNonQuery(); command.Connection.Close(); } }
Я пытаюсь добавить
Pooling=falseКак сказал Ладислав Мрнка, но всегда получал ошибку.
Я использую Среда Sql Server Management Studio и даже если я закрываю все соединения, я получаю ошибку.Если я закрою Среда Sql Server Management Studio затем база данных будет удалена :)
Надеюсь, это может помочь
Я получил ту же ошибку. В моем случае я просто закрыл соединение с базой данных, а затем снова подключился, как только в моем случае была добавлена новая модель, и новый контроллер был скомпонован. Однако это очень простое решение и не рекомендуется для всех сценариев, если вы хотите сохранить ваши данные.
У меня тогда была такая же проблема. Оказывается, решение состоит в том, чтобы закрыть соединение на вкладке Обозреватель серверов в Visual Studio. Поэтому, возможно, вы могли бы проверить, открыто ли соединение в Проводнике сервера.
Comments