依赖失败尝试的异常是返回bool值的可接受方式吗?

本文关键字:接受方 可接受 bool 返回 失败 异常 依赖 | 更新日期: 2023-09-27 18:07:19

这个查询:

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 opined: "select case when exists((select * from information_schema.;)

是否有类似的代码检查列是否存在?目前我的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);

依赖失败尝试的异常是返回bool值的可接受方式吗?

您应该只对异常(超出规范)的事情使用异常,无法找到表被认为是该方法的正常执行,因此不应该依赖异常的发生。

对于你的例子来说,不正常的事情是连接超时,这不是你的方法的标准操作。

相反,您应该查询sys.tablesINFORMATION_SCHEMA.TABLES表来查看您的表是否存在。

如果我面临同样的问题,我更喜欢在系统表中查找,正如Matthew指出的那样,检查表是否存在如果我使用的数据库不给我这样做的可能性,我会通过创建一个表来跟踪存在的表来模拟它。查询该表,而不是将代码包装在by try 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表

Update:这个DataReader Check例程如何:

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调用来进入数据的第一步。