Проверьте, существует ли база данных перед созданием
Это кажется довольно тривиальным, но теперь это расстраивает меня.
Я использую С# с SQL Server 2005 Express.
Я использую следующий код. Я хочу проверить, существует ли база данных до ее создания. Однако возвращаемое целое число равно -1, и именно так MSDN определяет, что вернет ExecuteNonQuery(). Сейчас база данных существует, но она все равно возвращает -1. Сказав это, как я могу заставить эту работу получить желаемый результат?
private static void checkInventoryDatabaseExists(ref SqlConnection tmpConn, ref bool databaseExists)
{
string sqlCreateDBQuery;
try
{
tmpConn = new SqlConnection("server=(local)\\SQLEXPRESS;Trusted_Connection=yes");
sqlCreateDBQuery = "SELECT * FROM master.dbo.sysdatabases where name =
\'INVENTORY\'";
using (tmpConn)
{
tmpConn.Open();
tmpConn.ChangeDatabase("master");
using (SqlCommand sqlCmd = new SqlCommand(sqlCreateDBQuery, tmpConn))
{
int exists = sqlCmd.ExecuteNonQuery();
if (exists <= 0)
databaseExists = false;
else
databaseExists = true;
}
}
}
catch (Exception ex) { }
}
Ответы
Ответ 1
Начиная с SQL Server 2005, устаревшие sysobjects
и sysdatabases
и эти представления каталога устарели. Сделайте это вместо этого - используйте систему sys.
схема - представления как sys.databases
private static bool CheckDatabaseExists(SqlConnection tmpConn, string databaseName)
{
string sqlCreateDBQuery;
bool result = false;
try
{
tmpConn = new SqlConnection("server=(local)\\SQLEXPRESS;Trusted_Connection=yes");
sqlCreateDBQuery = string.Format("SELECT database_id FROM sys.databases WHERE Name
= '{0}'", databaseName);
using (tmpConn)
{
using (SqlCommand sqlCmd = new SqlCommand(sqlCreateDBQuery, tmpConn))
{
tmpConn.Open();
object resultObj = sqlCmd.ExecuteScalar();
int databaseID = 0;
if (resultObj != null)
{
int.TryParse(resultObj.ToString(), out databaseID);
}
tmpConn.Close();
result = (databaseID > 0);
}
}
}
catch (Exception ex)
{
result = false;
}
return result;
}
Это будет работать с любым именем базы данных, которое вы передадите в качестве параметра, и вернет bool true = база данных существует, false = база данных не существует (или произошла ошибка).
Ответ 2
Прочитав это несколько лет, и там более чистый способ выразить это:
public static bool CheckDatabaseExists(string connectionString, string databaseName)
{
using (var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand($"SELECT db_id('{databaseName}')", connection))
{
connection.Open();
return (command.ExecuteScalar() != DBNull.Value);
}
}
}
Ответ 3
не должен
"SELECT * FROM master.dbo.sysdatabases where name = \'INVENTORY\'"
это?
"SELECT * FROM master.dbo.sysdatabases where name = 'INVENTORY'"
Также согласно MSDN
Для операторов UPDATE, INSERT и DELETE возвращаемое значение - это количество строк, на которые влияет команда. Когда триггер существует в вставленной или обновляемой таблице, возвращаемое значение включает в себя количество строк, затронутых как операцией вставки, так и обновлением, а также количеством строк, затронутых триггером или триггерами. Для всех других типов операторов возвращаемое значение равно -1. Если происходит откат, возвращаемое значение равно -1.
Вы выполняете SELECT, а не инструкцию DML. Почему вместо этого вы не используете метод ExecuteReader?
Ответ 4
Вы не можете использовать ExecuteNonQuery, потому что он всегда будет возвращать -1 для SELECT, как показывает ссылка MSDN.
Вам нужно будет использовать процесс, например, SELECT DB_ID('INVENTORY') AS DatabaseID
или использовать переменную/параметр: SELECT @DatabaseID = DB_ID('INVENTORY')
Ответ 5
Альтернативой запросам системных представлений является использование функции db_id, которая возвращает идентификатор базы данных, если она существует, иначе null. Пример T-SQL ниже:
if (db_id('INVENTORY') is null)
begin
return 0
end
else
begin
return 1
end
Ответ 6
Для удобства пользователей, если вы используете Entity Framework, это будет работать:
using (var ctx = new MyDataModel())
{
dbExists = System.Data.Entity.Database.Exists(ctx.Database.Connection);
}
Ответ 7
Взял код Стивена Ллойда и добавил некоторые асинхронные и SQL-инъекции.
public static async Task<bool> TestDatabase(string connectionString, string databaseName)
{
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand("SELECT db_id(@databaseName)", connection))
{
command.Parameters.Add(new SqlParameter("databaseName", databaseName));
connection.Open();
return (await command.ExecuteScalarAsync() != DBNull.Value);
}
}
Ответ 8
Если вы знаете, где находится файл базы данных, вы можете использовать File.Exists()
:
if (File.Exists(DatabaseFile))
{
//DoSomething
}