문제

This query:

string.Format("SELECT COUNT(*) FROM {0}", tableName);

...which I'm using as the guts of an "isValidTable(string tableName)" method, throws an exception if the tableName does not exist (specifically, "The specified table does not exist").

That being the case (it doesn't play nice, it throws up its hands if it doesn't recognize the table name) makes me wonder if this code:

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;
}

...could/should be simplified to:

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;
}

?

UPDATE

jp2code opined: "select case when exists((select * from information_schema.tables where table_name = '{0}')) then 1 else 0 end"

Is there similar code for checking if a column exists? Currently my isValidTable() and isValidColumn() queries are similar:

string tableQuery = string.Format("SELECT COUNT(*) FROM {0}", tableName);
string columnQuery = string.Format("SELECT COUNT({0}) FROM {1}", columnName, tableName);

...but if I were able to use this for isValidTable():

string.Format("select case when exists((select * from information_schema.tables where table_name = '{0}')) then 1 else 0 end",
tableName);

...is there also an extension of this that I could use for checking for valid columns? Something like:

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);

???

UPDATE 2

I realize that the suggested sql is "more better" than "my way," but for whatever reason, when I use "the preferred method," needed data tables are not recognized as existing (even though, of course, they do exist). Either the ancient version of software I'm using doesn't accept nested selects/sub-selects, or...???

At any rate, the comments tells the story:

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);
도움이 되었습니까?

해결책

You should only use exceptions for things that are exceptional (out of the norm), not being able to find a table is considered normal execution for that method, thus should not rely on exceptions to occur.

Things that are out of the norm for your example would be having a connection timeout, which is not standard operation for your method.

Instead, you should query the sys.tables or INFORMATION_SCHEMA.TABLES tables to see whether your table exists.

다른 팁

If I'm facing the same problem i prefer looking up in a System table, as Matthew pointed out, to check if a Table does exist or not and if the database I'm using doesn't give me the possibility to do that, I would simulate it by creating a table that keeps track of exist Tables. query that table instead of wrapping the code in a by try catch block. not an elegant solution but in my modest point of view much cleaner

If you continue using this, at least specify an SqlCeException that you catch and disregard, that way you don't unknowingly disregard other errors that might be happening.

As for checking if a table exists or not, see this popular post:

Check if table exists in SQL Server

Really, if your code works, you should not have any exceptions. So after debugging and your code is ready for release, it should look more like this:

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;
}

That particular SQL query uses a solution from this SO question:

Check if a SQL table exists

Update: How about this DataReader Check routine:

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;
}

The documentation on MSDN about DataReader 1.1 says (in the remarks) The default position of the SqlCeDataReader is prior to the first record. To begin accessing any data, you must call Read. So, it should start at Index = -1 and require a Read call to make the first step into the data.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top