我有一个MVC3和EF4Code First应用程序,它被配置为在模型更改时更改DB,方法是将DB Initializer设置为DropCreateDatabaseIfModelChanges<TocratesDb>
,其中TocratesDb
是我派生的DbContext
。
我现在已经通过向类添加属性对模型进行了更改,但是当EF尝试删除并重新创建DB时,我得到以下错误:
Cannot drop database "Tocrates" because it is currently in use.
我在这个数据库上完全没有打开任何其他连接。我假设我的cDbContext仍然具有到数据库的打开连接,但是我能对此做些什么呢?
NEW:现在我的问题是如何根据模型重新创建数据库。通过使用更通用的IDatabaseInitializer,我失去了这一点,不得不自己实现它。
发布于 2011-03-13 20:21:06
您的当前上下文必须具有打开的连接才能删除数据库。问题是,可能有其他打开的连接将阻止您的数据库初始化器。一个非常好的例子是在management studio中打开数据库中的任何表。另一个可能的问题是在应用程序的连接池中打开连接。
在MS SQL中,这可以通过将数据库切换到单用户模式并强制关闭所有连接和回滚未完成的事务来避免:
ALTER DATABASE Tocrates SET SINGLE_USER WITH ROLLBACK IMMEDIATE
您可以创建一个新的初始化器,它将首先调用此命令,然后删除数据库。请注意,您应该自己处理数据库连接,因为必须在同一连接上调用ALTER DATABASE
和DROP DATABASE
。
编辑:
下面是使用Decorator pattern的示例。您可以在构造函数中修改它并初始化内部初始化器,而不是将其作为参数传递。
public class ForceDeleteInitializer : IDatabaseInitializer<Context>
{
private readonly IDatabaseInitializer<Context> _initializer;
public ForceDeleteInitializer(IDatabaseInitializer<Context> innerInitializer)
{
_initializer = innerInitializer;
}
public void InitializeDatabase(Context context)
{
context.Database.SqlCommand("ALTER DATABASE Tocrates SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
_initializer.InitializeDatabase(context);
}
}
发布于 2013-11-14 20:25:48
我在EF6中发现这个失败,并出现了一个ALTER DATABASE statement not allowed within multi-statement transaction
错误。
解决方案是使用新的事务行为重载,如下所示:
context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, "ALTER DATABASE [" + context.Database.Connection.Database + "] SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
发布于 2011-12-28 04:45:59
我也有同样的问题。
我通过关闭在Visual Studio的Server Explorer视图下打开的连接解决了这个问题。
https://stackoverflow.com/questions/5288996
复制相似问题