Является ли использование исключения для неудачной попытки приемлемым способом возврата логического выражения?
Этот запрос:
string.Format("SELECT COUNT(*) FROM {0}", tableName);
... который я использую в качестве метода "isValidTable(string tableName)", вызывает исключение, если tableName не существует (в частности, "Указанная таблица не существует").
В этом случае (он не играет хорошо, он подбрасывает руки, если не распознает имя таблицы), я задаюсь вопросом, если этот код:
public bool isValidTable(string tableName)
{
bool validTable = false;
string tblQuery = string.Format("SELECT COUNT(*) FROM {0}", tableName);
try
{
SqlCeCommand cmd = new SqlCeCommand();
cmd.CommandText = tblQuery;
object objcnt = cmd.ExecuteScalar();
if ((objcnt != null) && (objcnt != DBNull.Value))
{
validTable = Int32.Parse(objcnt.ToString()) > 0;
}
else
{
MessageBox.Show("NULL returned from isValidTable(). Remove this line."); //<- I never see this; if this is the case, an exception has been thrown
}
}
catch
{
return false;
}
return validTable;
}
... можно / нужно упростить до:
public bool isValidTable(string tableName)
{
string tblQuery = string.Format("SELECT COUNT(*) FROM {0}", tableName);
try
{
SqlCeCommand cmd = new SqlCeCommand();
cmd.CommandText = tblQuery;
cmd.ExecuteScalar();
}
catch
{
return false;
}
return true;
}
?
ОБНОВИТЬ
Определяется jp2code: "выберите случай, когда существует ((выберите * из information_schema.tables, где table_name = '{0}')) затем 1 или 0, конец"
Существует ли подобный код для проверки существования столбца? В настоящее время мои запросы isValidTable() и isValidColumn() похожи:
string tableQuery = string.Format("SELECT COUNT(*) FROM {0}", tableName);
string columnQuery = string.Format("SELECT COUNT({0}) FROM {1}", columnName, tableName);
... но если бы я мог использовать это для isValidTable():
string.Format("select case when exists((select * from information_schema.tables where table_name = '{0}')) then 1 else 0 end",
tableName);
... есть ли также расширение этого, которое я мог бы использовать для проверки правильности столбцов? Что-то вроде:
string.Format("select case when exists((select * from information_schema.tables where table_name = '{0}' and column_name = '{1}')) then 1 else 0 end",
tableName, columnName);
???
ОБНОВЛЕНИЕ 2
Я понимаю, что предлагаемый sql "лучше", чем "мой путь", но по какой-то причине, когда я использую "предпочтительный метод", необходимые таблицы данных не распознаются как существующие (даже если, конечно, они существуют), Либо старая версия программного обеспечения, которую я использую, не принимает вложенные выборки / суб-выборки, или...???
В любом случае, комментарии рассказывают историю:
string tblQuery = string.Format("SELECT COUNT(*) FROM {0}", tableName);
// This is doubtless "more better," but when I use it, I get "No current work; no inventory file"
//string tblQuery = string.Format("select case when exists((select * from information_schema.tables where table_name = '{0}')) then 1 else 0 end", tableName);
3 ответа
Вы должны использовать исключения только для исключительных вещей (вне нормы), поскольку невозможность найти таблицу считается нормальным выполнением для этого метода, поэтому не следует полагаться на возникновение исключений.
Вещи, которые не являются нормой для вашего примера, будут иметь время ожидания соединения, которое не является стандартной операцией для вашего метода.
Вместо этого вы должны запросить sys.tables
или же INFORMATION_SCHEMA.TABLES
таблицы, чтобы увидеть, существует ли ваша таблица.
Если я сталкиваюсь с той же проблемой, я предпочитаю искать в Системной таблице, как указал Мэтью, чтобы проверить, существует ли Таблица или нет, и если база данных, которую я использую, не дает мне возможности сделать это, Я бы смоделировал это, создав таблицу, которая отслеживает существующие таблицы. запросить эту таблицу вместо переноса кода в блок try by catch. не элегантное решение, но на мой скромный взгляд намного чище
Если вы продолжаете использовать это, по крайней мере, укажите SqlCeException
что вы ловите и игнорируете, таким образом, вы не игнорируете другие ошибки, которые могут произойти.
Что касается проверки, существует ли таблица, посмотрите этот популярный пост:
Проверьте, существует ли таблица в SQL Server
Действительно, если ваш код работает, у вас не должно быть никаких исключений. Поэтому после отладки и когда ваш код готов к выпуску, он должен выглядеть примерно так:
public bool isValidTable(string tableName)
{
bool validTable = false;
string tblQuery =
string.Format("select case when exists((select * from information_schema.tables where table_name = '{0}')) then 1 else 0 end",
tableName);
SqlCeCommand cmd = new SqlCeCommand();
cmd.CommandText = tblQuery;
try
{
cmd.Connection.Open();
object objcnt = cmd.ExecuteScalar();
if ((objcnt != null) && (objcnt != DBNull.Value))
{
validTable = Int32.Parse(objcnt.ToString()) > 0;
}
}
finally
{
cmd.Connection.Close();
}
return validTable;
}
Этот конкретный запрос SQL использует решение из этого вопроса SO:
Проверьте, существует ли таблица SQL
Обновление: Как насчет этой процедуры проверки DataReader:
public bool isValidTable(string tableName)
{
bool validTable = false;
string tblQuery =
string.Format("select * from information_schema.tables where table_name='{0}'",
tableName);
SqlCeCommand cmd = new SqlCeCommand();
cmd.CommandText = tblQuery;
try
{
cmd.Connection.Open();
// I don't know if this works because I don't have .NET 1.1
SqlCeDataReader r = cmd.ExecuteReader();
validTable = r.Read();
}
finally
{
cmd.Connection.Close();
}
return validTable;
}
Документация по MSDN о DataReader 1.1 гласит (в комментариях) Положение SqlCeDataReader по умолчанию предшествует первой записи. Чтобы начать доступ к любым данным, вы должны позвонить в Read. Таким образом, он должен начинаться с Index = -1 и требовать вызова Read, чтобы сделать первый шаг в данные.