“无法删除数据库,因为它当前正在使用中”。怎么修?
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”(如果存在,但通常是),然后删除另一个数据库。这应该总是有效的!
约翰老师
【讨论】:
以上是关于“无法删除数据库,因为它当前正在使用中”。怎么修?的主要内容,如果未能解决你的问题,请参考以下文章