C# 有没有一种方法可以使用ADO.NET来确定与任何数据提供程序一起工作的数据库中是否存在表?

C# 有没有一种方法可以使用ADO.NET来确定与任何数据提供程序一起工作的数据库中是否存在表?,c#,sql,ado.net,C#,Sql,Ado.net,有没有一种方法可以使用ADO.NET来确定与任何数据提供程序一起工作的数据库中是否存在表 我目前正在做这样的事情: bool DoesTableExist(string tableName) { DbCommand command = this.dbConnection.CreateCommand(); command.CommandText = "SELECT 1 FROM " + tableName; try { using (DbDataRe

有没有一种方法可以使用ADO.NET来确定与任何数据提供程序一起工作的数据库中是否存在表

我目前正在做这样的事情:

bool DoesTableExist(string tableName)
{
    DbCommand command = this.dbConnection.CreateCommand();
    command.CommandText = "SELECT 1 FROM " + tableName;
    try
    {
        using (DbDataReader reader = command.ExecuteReader())
        {
            return true;
        }
    }
    catch (DbException)
    {
        return false;
    }
}

我希望有一种不涉及捕获异常的方法。

好的,您可以使用
Connection.GetSchema(“TABLES”)
方法

这将返回一个
DataTable
,其中将包含数据库中所有表的行。从这里,您可以对照该表进行检查,并查看该表是否存在

然后可以采取进一步措施:

    private static bool DoesTableExist(string TableName)
    {
        using (SqlConnection conn = 
                     new SqlConnection("Data Source=DBServer;Initial Catalog=InitialDB;User Id=uname;Password=pword;"))
        {
            conn.Open();

            DataTable dTable = conn.GetSchema("TABLES", 
                           new string[] { null, null, "MyTableName" });

            return dTable.Rows.Count > 0;
        }
    }

如果您使用的是.NET 3.5,那么您也可以将其作为一种扩展方法。

对Kyle的回答进行了一些小改进,以说明不同的数据库(例如oracle与ms sql server)将表名列放在“Tables”表的不同索引中:

publicstaticboolcheckiftableexists(此DbConnection连接,字符串tableName)//连接=((DbContext)\u context).Database.connection;
{
if(连接==null)
抛出新ArgumentException(nameof(connection));
if(connection.State==ConnectionState.Closed)
connection.Open();
var tableInfoOnTables=connection//0
.GetSchema(“表”)
.栏目
.Cast()
.Select(x=>x.ColumnName?.ToLowerInvariant()??“”
.ToList();
var tableNameColumnIndex=tableInfoOnTables.FindIndex(x=>x.Contains(“table.ToLowerInvariant())&&x.Contains(“name.ToLowerInvariant());//顺序
tableNameColumnIndex=tableNameColumnIndex==-1?tableInfoOnTables.FindIndex(x=>x.Contains(“table.ToLowerInvariant()):tableNameColumnIndex;//顺序
tableNameColumnIndex=tableNameColumnIndex==-1?tableInfoOnTables.FindIndex(x=>x.Contains(“name.ToLowerInvariant()):tableNameColumnIndex;//顺序
如果(tableNameColumnIndex==-1)
抛出新的ApplicationException(“未能发现数据库字典表中哪个列包含表名”);
var约束=新字符串[tableNameColumnIndex+1];
约束[tableNameColumnIndex]=表名;
返回connection.GetSchema(“表”,约束)?.Rows.Count>0;
}
//0不同的数据库具有不同的列数和分配给它们的不同名称
//
//模式,表名,类型->oracle
//表目录、表模式、表名称、表类型->mssqlserver
//
//因此,我们需要弄清楚哪个列表示表名,哪个列表示该表名的目标

您可能会问这个问题,因为您在那里检测到一些代码气味,所以将此作为一种恭维:使用异常作为流控制不是最佳做法。在事务打开时不起作用(请参阅:)。
    public static bool CheckIfTableExists(this DbConnection connection, string tableName) //connection = ((DbContext) _context).Database.Connection;
    {
        if (connection == null)
            throw new ArgumentException(nameof(connection));

        if (connection.State == ConnectionState.Closed)
            connection.Open();

        var tableInfoOnTables = connection //0
            .GetSchema("Tables")
            .Columns
            .Cast<DataColumn>()
            .Select(x => x.ColumnName?.ToLowerInvariant() ?? "")
            .ToList();

        var tableNameColumnIndex = tableInfoOnTables.FindIndex(x => x.Contains("table".ToLowerInvariant()) && x.Contains("name".ToLowerInvariant())); //order
        tableNameColumnIndex = tableNameColumnIndex == -1 ? tableInfoOnTables.FindIndex(x => x.Contains("table".ToLowerInvariant())) : tableNameColumnIndex; //order
        tableNameColumnIndex = tableNameColumnIndex == -1 ? tableInfoOnTables.FindIndex(x => x.Contains("name".ToLowerInvariant())) : tableNameColumnIndex; //order

        if (tableNameColumnIndex == -1)
            throw new ApplicationException("Failed to spot which column holds the names of the tables in the dictionary-table of the DB");

        var constraints = new string[tableNameColumnIndex + 1];
        constraints[tableNameColumnIndex] = tableName;

        return connection.GetSchema("Tables", constraints)?.Rows.Count > 0;
    }
    //0 different databases have different number of columns and different names assigned to them
    //
    //     SCHEMA,TABLENAME,TYPE -> oracle
    //     table_catalog,table_schema,table_name,table_type -> mssqlserver
    //
    //  we thus need to figure out which column represents the tablename and target that one