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

Posted

技术标签:

【中文标题】“无法删除数据库,因为它当前正在使用中”。怎么修?【英文标题】:"Cannot drop database because it is currently in use". How to fix? 【发布时间】:2011-08-10 00:41:22 【问题描述】:

有了这个简单的代码,当我运行它时,我得到“无法删除数据库“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; 

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

【问题讨论】:

CTP5 已死。当前版本是 EF 4.1。 【参考方案1】:

问题是您的应用程序可能仍然与数据库保持一些连接(或者另一个应用程序也保持连接)。如果有任何其他打开的连接,则无法删除数据库。第一个问题可能可以通过关闭连接池(将Pooling=false 添加到您的连接字符串)或在删除数据库之前清除池(通过调用SqlConnection.ClearAllPools())来解决。

这两个问题都可以通过强制删除数据库来解决,但为此您需要自定义数据库初始化程序,将数据库切换到单用户模式,然后将其删除。 Here 是如何实现这一目标的一些示例。

【讨论】:

Pooling=false 完成了这项工作。谢谢! @LadislavMrnka 如果我有 pooling=false 并且我已经设置了 single_user,但仍然收到此错误消息,该怎么办?【参考方案2】:

我要疯了!我在SQL Server Management Studio (SSMS) 中有一个开放的数据库连接,并打开了一个表查询以查看一些单元测试的结果。在 Visual Studio 中重新运行测试时,我希望它始终 drop 数据库即使连接在 SSMS 中打开。

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

Entity Framework Database Initialization

诀窍是在自定义Initializer 中覆盖InitializeDatabase 方法。

为了good而将相关部分复制到这里DUPLICATION... :)

如果数据库已经存在,你可能会遇到这样的情况 一个错误。异常“无法删除数据库,因为它当前是 在使用中”可以提高。活动连接时会出现此问题 保持连接到正在处理的数据库 删除。一个技巧是重写 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);
    

【讨论】:

这是放弃用户进行自动化测试的最简单、最直接的方法。 IF EXISTS就完美了。 @ericosg 如何使用IF EXISTS 适用于 mdf 文件 使用 Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\wingtiptoys.mdf;Integrated Security=True ? @Kiquenet 喜欢这个***.com/questions/679000/…【参考方案3】:

这是一个非常激进的数据库(重新)初始化程序,用于 EF 代码优先和迁移;使用它会带来危险,但对我来说它似乎可以重复运行。会的;

    强制断开任何其他客户端与数据库的连接 删除数据库。 使用迁移重建数据库并运行 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”技巧,但我不确定它是否是必需的,或者只是一个带大括号的措施。它肯定会进一步减慢测试速度。

【讨论】:

【参考方案4】:

这些解决方案都不适合我。我最终编写了一个有效的扩展方法:

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

【讨论】:

我们可以使用database.Connection.CreateCommand(),而不是database.Connection.CreateCommand()。否则这是一个很好的解决方案。 请帮助我理解 - database.Connection.CreateCommand() 有什么问题?我没有任何问题。谢谢! 没有,只是更冗长而已。 如何使用? Database.SetInitializer(new EventDatabaseInitializer()); ?【参考方案5】:

我尝试像 Ladislav Mrnka 所说的那样添加Pooling=false,但总是出错。 我正在使用 Sql Server Management Studio,即使我关闭了所有连接,我也会收到错误消息。

如果我关闭 Sql Server Management Studio,则数据库将被删除 :) 希望这可以帮助

【讨论】:

很可能你没有关闭Sql Server Management Studio 中的所有连接,请注意,通常你有TWO 连接在那里运行,one for the object explorer AND one for the current query 如果你关闭/切换它们应该可以工作跨度> 正如@DrCopyPaste 所说,SSMS 在保持与数据库的连接方面非常激进。除了关闭应用程序之外,我还没有找到处理它的好方法。 @SteveCooper 你可以通过脚本来做到这一点:***.com/a/11627/2186023 不需要关闭 SSMS,然后在你完成初始化/更新后,你可以重用 ssms,它会记住你最后的连接(虽然他们丢失了),只需按两次F5,它将执行第二次 @anthoLB29 从 2013 年开始,一个古老但仍然很好的东西!我刚刚花了 10 分钟重置我的密码来给你 +1。当我读到它时,我笑了,因为它听起来很合乎逻辑,但又太容易了,而且好得令人难以置信。好吧,事实并非如此!再见实体框架DropCreateDatabaseAlways 问题...【参考方案6】:

我遇到了同样的错误。就我而言,我只是关闭了与数据库的连接,然后在我的情况下添加了新模型并搭建了新控制器后重新连接。但是,这是一个非常简单的解决方案,如果您想保留数据,则不建议在所有情况下使用。

【讨论】:

【参考方案7】:

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

【讨论】:

【参考方案8】:

这很简单,因为您仍在某处使用相同的数据库,或者连接仍处于打开状态。 所以只需先执行“USE master”(如果存在,但通常是),然后删除另一个数据库。这应该总是有效的!

约翰老师

【讨论】:

以上是关于“无法删除数据库,因为它当前正在使用中”。怎么修?的主要内容,如果未能解决你的问题,请参考以下文章

画布文本单击不起作用。怎么修?

函数没有易失性。怎么修?

Hold Violation怎么修?

错误:Apache 意外关闭。怎么修?

wordpress 中带有 ' 的图片链接替换为 %E2%80%99。怎么修?

CORS 预检选项请求的 403 错误。怎么修?