Я играю с некоторыми подключениями к БД через WinForms и WebService, и я обнаружил, что при использовании веб-службы подключения не закрываются. Это вызывает затруднения в моем автоматическом тесте, потому что я уничтожаю и воссоздаю базу данных между тестами, поэтому у меня всегда одинаковое начальное состояние для каждого теста.
Фактический код доступа к данным для вызова одинаков в обоих случаях, например:
using (DataHandler handler = new DataHandler(Config.ConnectionString()))
{
return handler.GetDbVersion();
}
DataHandler использует контекст данных (созданный с помощью SqlMetal), чтобы загрузить целое число из таблицы БД и вернуть его.
Метод Dispose of DataHandler закрывает соединение и контекст данных:
public void Dispose()
{
_data.Connection.Close();
_data.Connection.Dispose();
_data.Dispose();
}
При запуске непосредственно из модульного теста - он проходит, после чего в БД не остается никаких соединений.
select spid, status, loginame, hostname, blocked, db_name(dbid), cmd from master..sysprocesses where db_name(dbid) = 'TEST_DATABASE'
Затем я обертываю это в [WebMethod] и помещаю в экземпляр IIS7:
[WebMethod]
public int GetDatabaseVersionNumber()
{
using (DataHandler handler = new DataHandler(Config.ConnectionString()))
{
return handler.GetDbVersion();
}
}
И тест вызывает веб-службу:
int dbVersion = _webService.GetDatabaseVersionNumber();
Веб-служба создает контекст данных - получает номер - вызывает Dispose и затем возвращает номер. Однако соединение все еще «спит» в БД. Это означает, что когда я пытаюсь уничтожить и воссоздать базу данных для следующего теста, сбрасывается база данных (активное соединение).
select spid, status, loginame, hostname, blocked, db_name(dbid), cmd from master..sysprocesses where db_name(dbid) = 'TEST_DATABASE'
54 sleeping IIS APPPOOL\ASP.NET v4.0 PETE 0 TEST_DATABASE AWAITING COMMAND
Я предполагаю, что это какой-то пул соединений, который обрабатывают IIS и SQL Server, чтобы уменьшить накладные расходы на все открытие и закрытие соединений от веб-запросов (полагаю, я не хотел бы связываться с этим в контексте развертывания веб-службы)
Однако для тестов я хотел бы отключить это соединение, чтобы я мог восстановить свою базу данных.
Какой лучший способ справиться с этим? (Это то, что мне нужно установить в IIS или в тестовой базе данных? Могу ли я определить это в строке подключения, чтобы это происходило только на тесте?)
Для информации
Решено добавлением следующего кода к методу тестирования:
if (data.DatabaseExists())
{
data.ExecuteCommand("ALTER DATABASE TEST_DATABASE SET SINGLE_USER WITH ROLLBACK IMMEDIATE;");
data.ExecuteCommand("ALTER DATABASE TEST_DATABASE SET MULTI_USER;");
data.DeleteDatabase();
}
Обновление
Я обнаружил, что могу обойти эту проблему, добавив «Pooling = false» в строку подключения в модуле Test Unit App.Config. Кажется, это работает намного лучше, чем принудительное закрытие соединений, потому что, когда вы принудительно закрываете их, иногда БД недоступна для следующего теста в наборе (вы получаете ошибку типа «нет обслуживания на другом конце канала», потому что SQL ушел, но .net думает, что он все еще там).