"현재 사용 중이므로 데이터베이스를 삭제할 수 없습니다." 어떻게 고치는 지?
이 간단한 코드를 사용하면 "현재 사용 중이기 때문에"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; }
내 코드에서 데이터베이스를 제거하려면 어떻게해야합니까? 감사
문제는 응용 프로그램이 여전히 데이터베이스에 대한 일부 연결을 보유하고 있거나 다른 응용 프로그램도 연결을 보유한다는 것입니다. 열려있는 다른 연결이있는 데이터베이스는 삭제할 수 없습니다. 첫 번째 문제는 연결 풀링을 끄 Pooling=false
거나 (연결 문자열에 추가 ) 데이터베이스를 삭제하기 전에 풀을 지우면 (을 호출하여 SqlConnection.ClearAllPools()
) 해결할 수 있습니다 .
두 가지 문제는 데이터베이스를 강제로 삭제하여 해결할 수 있지만이를 위해서는 데이터베이스를 단일 사용자 모드로 전환 한 후 삭제하는 사용자 지정 데이터베이스 이니셜 라이저가 필요합니다. 여기에 그것을 달성하는 방법을 몇 가지 예입니다.
나는 이것에 미쳐 가고 있었다! 내부에 열린 데이터베이스 연결이 SQL Server Management Studio (SSMS)
있고 일부 단위 테스트의 결과를보기 위해 테이블 쿼리가 열려 있습니다. 다시 실행 비주얼 스튜디오 I 내부 테스트가 원하는 경우 drop
데이터베이스 항상 경우에도 연결이 SSMS에 열려 있습니다.
제거하는 확실한 방법은 다음과 같습니다 Cannot drop database because it is currently in use
.
트릭은 InitializeDatabase
custom 내부의 메서드 를 재정의 하는 것 Initializer
입니다.
good
복제를 위해 여기에 관련 부분을 복사했습니다 ... :)
데이터베이스가 이미 존재하는 경우 오류가 발생할 수 있습니다. "현재 사용 중이므로 데이터베이스를 삭제할 수 없습니다"예외가 발생할 수 있습니다. 이 문제는 활성 연결이 삭제중인 데이터베이스에 계속 연결되어있을 때 발생합니다. 트릭은 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);
}
}
이것은 마이그레이션이있는 EF 코드 우선을위한 매우 공격적인 데이터베이스 (재) 이니셜 라이저입니다. 당신의 위험에 그것을 사용하지만 그것은 나를 위해 꽤 반복적으로 실행되는 것 같습니다. 그것은 것입니다;
- DB에서 다른 클라이언트를 강제로 분리
- DB를 삭제합니다.
- 마이그레이션을 통해 DB를 재 구축하고 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'트릭을 사용하지만 이것이 필요한지 아니면 그냥 벨트와 브레이스 측정인지 확실하지 않습니다. 그것은 확실히 테스트 속도를 더 늦추는 데 기여할 것입니다.
이러한 솔루션 중 어느 것도 나를 위해 일하지 않았습니다. 결국 작동하는 확장 메서드를 작성했습니다.
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();
}
}
Pooling=false
Ladislav Mrnka가 말한 것처럼 추가하려고 시도 했지만 항상 오류가 발생했습니다.
내가 사용하고 SQL Server Management Studio를 하고 심지어 내가 가까이 모든 연결하면, 나는 오류가 발생합니다.
Sql Server Management Studio 를 닫으면 데이터베이스가 삭제됩니다. :)
도움이되기를 바랍니다.
I got the same error. In my case, I just closed the connection to the database and then re-connected once the in my case the new model was added and a new controller was scaffolded. That is however a very simple solution and not recommended for all scenarios if you want to keep your data.
I got the same problem back then. Turns out the solution is to close the connection in Server Explorer tab in Visual Studio. So maybe you could check whether the connection is still open in the Server Explorer.
Its simple because u're still using the same db somewhere, or a connection is still open. So just execute "USE master" first (if exist, but usually is) and then drop the other db. This always should work!
Grz John
'program story' 카테고리의 다른 글
PHP cURL HTTP PUT (0) | 2020.12.11 |
---|---|
MongoDB에서 $ in 쿼리에 전달되는 최대 매개 변수 수는 얼마입니까? (0) | 2020.12.11 |
연결된 응용 프로그램으로 파일 열기 (0) | 2020.12.11 |
플롯 할 matplotlib Axes 인스턴스를 얻는 방법은 무엇입니까? (0) | 2020.12.11 |
SSL 연결을 설정할 수 없습니다. SSL 인증서를 수정하려면 어떻게해야합니까? (0) | 2020.12.11 |