“无法删除数据库,因为它目前正在使用”。 怎么修?

有了这个简单的代码,我得到了“不能删除数据库”test_db“,因为它正在使用”(CleanUp方法),因为我运行它。

[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; } 

如何强制我的代码删除数据库? 谢谢

问题是你的应用程序可能仍然保持一些连接到数据库(或另一个应用程序持有连接)。 有其他打开的连接的地方,数据库不能被删除。 第一个问题可以通过closures连接池(将Pooling=false添加到连接string)或删除数据库之前清除池(通过调用SqlConnection.ClearAllPools() )来解决。

这两个问题都可以通过强制删除数据库来解决,但是您需要自定义数据库初始值设定项,将数据库切换到单用户模式,之后将其删除。 下面是一些如何实现这个function的例子。

我正在为此疯狂! 我在SQL Server Management Studio (SSMS)内部有一个打开的数据库连接,并打开一个表查询以查看某些unit testing的结果。 当在Visual Studio中重新运行testing时,我希望它始终drop数据库, 即使连接在SSMS中打开。

这是摆脱Cannot drop database because it is currently in use的明确方法, Cannot drop database because it is currently in use

entity framework数据库初始化

诀窍是重写自定义Initializer InitializeDatabase方法。

复制相关部分在这里为了good DUPLICATION … 🙂

如果数据库已经存在,您可能会遇到有错误的情况。 可以引发exception“无法删除数据库,因为它当前正在使用”。 当活动连接保持连接到正在被删除的数据库时,会发生此问题。 诀窍是重写InitializeDatabase方法并更改数据库。 这告诉数据库closures所有的连接,并且如果一个事务是打开的,回滚这个。

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

对于EF代码,这是一个非常积极的数据库(重新)初始化程序,首先进行迁移; 使用它在你的危险,但它似乎运行相当可重复的我。 它会;

  1. 从数据库强制断开任何其他客户端
  2. 删除数据库。
  3. 用迁移重build数据库并运行Seed方法
  4. 花时间! (注意testing框架的超时限制;默认的60秒超时可能不够)

这是class级。

 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”技巧,但我不确定是需要还是只是一个腰带和大括号的措施。 这肯定会有助于减缓testing。

没有任何解决scheme为我工作。 我结束了写作扩展方法:

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

我尝试添加像Ladislav Mrnka说的Pooling=false但总是得到错误。
我正在使用Sql服务器pipe理工​​作室 ,即使我closures所有的连接,我得到的错误。

如果我closuresSql Server Management Studio,那么数据库被删除:)
希望这可以帮助

我得到了同样的错误。 就我而言,我只是closures了与数据库的连接,然后重新连接,一旦在我的情况下,新的模型被添加,并且一个新的控制器被脚手架。 然而,这是一个非常简单的解决scheme,如果你想保留你的数据,不build议用于所有场景。

那时我也遇到了同样的问题。 原来,解决方法是closuresVisual Studio中服务器资源pipe理器选项卡中的连接。 所以也许你可以检查连接是否仍然在服务器资源pipe理器中打开。