实体框架无法删除数据库,数据库正在使用中
本文关键字:数据库 删除 实体 框架 | 更新日期: 2023-09-27 18:00:42
我(和许多其他人一样)遇到了无法让NUnit测试删除测试夹具的[SetUp]
中的数据库的问题。
我想要实现的目标
我想编写集成测试来测试我的代码,并验证预期结果是否存储在数据库中(断言CRUD方法)。也就是说,和我希望能够在SqlServer中实际显示表,并查看数据库中的结果。最后一部分似乎很难实现。。。
出了什么问题
我可以连续多次运行测试。每次在[SetUp]
中重新创建数据库,并且测试通过断言。只要我想在SqlServer中的实际数据库中检查我的结果,它就会耗尽。一旦我从SqlServer打开了一个连接,[SetUp]
方法就不允许删除数据库,因为它有打开的连接。
我试过什么
- 数据库初始值设定项
- ALTER数据库SET SINGLE_USER WITH ROLLBACK IMMEDIATE
- Pooling=false添加到连接字符串
我从这篇和这篇SO帖子中得到了这些想法。
我有什么
[SetUp]
方法:
[SetUp]
public void SetUp()
{
// TenantSeedInitializer extends the
// DropCreateDatabaseAlways<TenantApplicationTestContext> class
Database.SetInitializer(new TenantSeedInitializer());
_applicationContext = new TenantApplicationTestContext();
_applicationContext.Database.ExecuteSqlCommand("ALTER DATABASE " +
TenantApplicationTestContext.DatabaseName +
" SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
}
[TearDown]
方法:
[TearDown]
public void TearDown()
{
SqlConnection.ClearAllPools();
}
还有一个非常直接的测试:
[Test]
public void AddTenant()
{
// add a new tenant to the database and verify that there
// there is only one tenant present in the table
}
正如我所说,连续运行此测试几次非常有效,直到我尝试在SqlServer中打开表为止。
两个不同的(对我来说未解决的)错误场景
1) 或者我不被允许查看表格,因为来自visual studio的连接仍然打开
数据库"TestTenantDatabase"已打开,一次只能有一个用户。
添加SqlConnection.ClearAllPools();
似乎并不能解决这个问题。
2) 或者我被允许在SqlServer中查看表,然后我不再被允许从[SetUp]
设备中删除数据库
无法删除数据库"TestTenantDatabase",因为它当前正在使用中。
关闭SqlServer是我所知道的摆脱这种情况的唯一方法。但后来我发现自己在白天经常重新启动SqlServer。。。(关闭数据库连接的选项也会有所帮助,但我找不到它)。
有人能引导我度过难关吗?
此消息:
数据库"TestTenantDatabase"已打开,并且只能有一个用户。
正在发生,因为您已将数据库设置为单用户。通常情况下,您会终止与数据库的其他连接,并使您的连接成为唯一可以访问该数据库的连接。但是,如果您更改数据库上下文,则其他应用程序(如Visual Studio)可能会连接进来,并成为单用户,从而有效地将您锁定。
在你的安装夹具中试试这个:
use TestTenantDatabase;
alter database TestTenantDatabase set single_user with rollback immediate;
use master;
drop database TestTenantDatabase;
如果您在数据库中设置单个用户,则您将成为单个用户。然后,如果您更改为master,然后在同一批中删除数据库,它应该会击败任何试图连接到它的人。
另一个选项是设置为脱机,而不是single_user,但是,当您删除数据库时,它不会删除数据库。mdf&ldf(和任何.ndf)文件,因此在为另一组测试重新创建数据库时可能会遇到问题。
如果在运行single_user时遇到与死锁相关的错误,请将死锁优先级设置为高。如果要重用连接,可以在断开后将其设置为正常。