是否依赖于失败尝试的异常是一种可接受的返回bool的方法?

时间:2013-04-02 20:54:07

标签: c# refactoring compact-framework windows-ce .net-1.0

此查询:

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 at exists((select * from information_schema.tables where table_name ='{0}'))然后1 else 0 end”

是否有用于检查列是否存在的类似代码?目前我的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 个答案:

答案 0 :(得分:2)

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

超出您的示例标准的事情将是连接超时,这不是您的方法的标准操作。

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

答案 1 :(得分:1)

如果我遇到同样的问题,我更喜欢在System表中查找,正如Matthew指出的那样,检查表是否存在 如果我正在使用的数据库没有给我这样做的可能性,我会通过创建一个跟踪现有表的表来模拟它。查询该表而不是将代码包装在try catch块中。不是一个优雅的解决方案,但在我的谦虚的观点更清洁

答案 2 :(得分:1)

如果你继续使用它,至少指定一个你抓住并忽略的SqlCeException,这样你就不会在不知不觉中忽视可能发生的其他错误。

至于检查表是否存在,请参阅此热门帖子:

Check if table exists in 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问题的解决方案:

Check if a SQL table exists

更新:这个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;
}

documentation on MSDN about DataReader 1.1表示(在备注中) SqlCeDataReader的默认位置在第一条记录之前。要开始访问任何数据,您必须调用Read。因此,它应该从Index = -1开始,并且需要Read调用才能进入数据的第一步。

相关问题