Ayant ce code simple, j'obtiens "Impossible de supprimer la base de données" test_db "car elle est actuellement utilisée" (méthode CleanUp) telle que je l'ai exécutée.
[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 a une propriété comme celle-ci
public DbSet<Client> Clients { get; set; }
Comment peut forcer mon code à supprimer la base de données? Merci
Le problème est que votre application conserve probablement encore une connexion à la base de données (ou une autre application conserve également une connexion). La base de données ne peut pas être supprimée s'il existe une autre connexion ouverte. Le premier problème peut probablement être résolu en désactivant le regroupement de connexions (ajoutez Pooling=false
à votre chaîne de connexion) ou en effaçant le pool avant de supprimer la base de données (en appelant SqlConnection.ClearAllPools()
).
Les deux problèmes peuvent être résolus en imposant la suppression de la base de données, mais pour cela, vous avez besoin d'un initialiseur de base de données personnalisé, dans lequel vous basculez la base de données en mode utilisateur unique puis supprimez-la. Voici voici quelques exemples pour y parvenir.
Je devenais fou avec ça! J'ai une connexion de base de données ouverte dans SQL Server Management Studio (SSMS)
et une requête de table ouverte pour voir le résultat de certains tests unitaires. Lorsque je ré-exécute les tests dans Visual Studio, je souhaite que la drop
de la base de données soit toujours EVEN IF la connexion est ouverte dans SSMS.
Voici le moyen idéal pour se débarrasser de Cannot drop database because it is currently in use
:
Initialisation de la base de données Entity Framework
L'astuce consiste à surcharger la méthode InitializeDatabase
à l'intérieur de la Initializer
personnalisée.
Copier la partie pertinente ici dans un souci de good
DUPLICATION ... :)
Si la base de données existe déjà, vous pouvez tomber sur le cas d’avoir une erreur. L'exception «Impossible de supprimer la base de données car il s'agit actuellement de en cours d'utilisation »peut augmenter. Ce problème se produit lorsqu'une connexion active reste connecté à la base de données en cours de traitement supprimé. Une astuce consiste à remplacer la méthode InitializeDatabase et à modifier la base de données. Cela indique à la base de données de fermer toutes les connexions et si une transaction est ouverte pour annuler celle-ci.
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);
}
}
Il s’agit d’un (ré) initialiseur de base de données très agressif pour le code EF en premier avec les migrations; utilisez-le à vos risques et périls, mais il semble fonctionner assez souvent pour moi. Ce sera;
Voici la classe.
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);
}
}
Utilisez-le comme ça;
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);
}
}
J'utilise également le truc 'Pooling = false' de Ladislav Mrnka, mais je ne suis pas sûr que ce soit nécessaire ou juste une mesure de ceinture et d'accolades. Cela contribuera certainement à ralentir davantage le test.
Aucune de ces solutions n'a fonctionné pour moi. J'ai fini par écrire une méthode d'extension qui fonctionne:
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();
}
}
J'essaie d'ajouter Pooling=false
comme l'a dit Ladislav Mrnka mais j'ai toujours l'erreur.
J'utilise SQL Server Management Studio et même si je ferme toute la connexion, j'obtiens l'erreur.
Si je ferme SQL Server Management Studio alors la base de données est supprimée :)
J'espère que cela peut aider
J'ai eu la même erreur. Dans mon cas, je viens de fermer la connexion à la base de données puis de me reconnecter une fois le nouveau modèle ajouté et un nouveau contrôleur échafaudé. C'est cependant une solution très simple et déconseillée pour tous les scénarios si vous souhaitez conserver vos données.
J'ai eu le même problème à l'époque. Il s'avère que la solution consiste à fermer la connexion dans l'onglet Explorateur de serveurs de Visual Studio. Alors, vous pourriez peut-être vérifier si la connexion est toujours ouverte dans l'Explorateur de serveurs.