C# 使用 OleDbSchemaTable 获取数据库表名与列名

小鹿同学
小鹿同学
发布时间:2026-10-15 | 3人浏览过
原创

在C#开发中,有时需要动态获取数据库的结构信息(如表名、字段名)。本文将展示如何利用 OLE DB Provider 的标准 Schema 接口,快速获取数据库中所有的表名及其对应的列定义,并附带从已有 DataTable 中提取列名的简便写法。

实现原理与准备

C# 可以通过 System.Data.OleDb 命名空间下的 OleDbConnection 对象调用 GetOleDbSchemaTable 方法来查询数据库的系统视图。该方法返回一个包含模式信息的 DataTable,其中每一行代表一个元数据结构(如一张表或一个列)。

主要依赖的类:
- System.Data.OleDb.OleDbConnection
- System.Data.OleDb.OleDbSchemaGuid:用于指定要查询的模式类型(如 Tables, Columns, Indexes 等)

第1步:获取数据库中所有表名

目的:列出当前连接数据库中包含的所有用户表名称。

入口:调用封装好的 GetTablesName 方法。

动作说明:

  1. 初始化一个 List<string> 用于存储结果。
  2. 调用 DbDataHelper.GetCon().GetOleDbSchemaTable,传入 OleDbSchemaGuid.Tables 作为第一个参数。
  3. 设置过滤数组:前三个参数为 null(不限制Catalog/Schema/Constraint),第四个参数传 "TABLE" 以排除系统视图或临时表(视具体驱动而定)。
  4. 遍历返回的 DataTable 每一行,读取 TABLE_NAME 字段值加入列表。
List<string> GetTablesName(Guid gtype,string tableType ="TABLE", string strTableName =null , string itemIndex= "TABLE_NAME")
{
    List<string> strNames = new List<string>();

    // gtype通常传入 OleDbSchemaGuid.Tables
    DataTable dsTablesData = DbDataHelper.GetCon().GetOleDbSchemaTable(gtype, new Object[] { null, null, strTableName, tableType });

    foreach (DataRow item in dsTablesData.DefaultView.Table.Rows)
    {
        strNames.Add(item[itemIndex].ToString());
    }

    return strNames;
}

第2步:获取指定表的所有列名及类型

目的:获取某张表内的详细字段结构,包括字段顺序、名称和数据类型。

入口:调用 GetColsName 方法。

动作说明:

  1. 创建 List<Dictionary<string, string>> 预分配空间,数量等于行数,避免扩容开销。
  2. 调用 GetOleDbSchemaTable,传入 OleDbSchemaGuid.Columns,并指定目标 tableName。
  3. 遍历返回的数据行,读取 ORDINAL_POSITION(列序号)和 DATA_TYPE(数据类型ID)。
  4. 根据序号将列名映射存入字典列表。注意索引转换:序号通常从1开始,数组索引从0开始,故使用 pos-1。
List<Dictionary<string, string>>  GetColsName(Guid gtype,string tableName,string itemIndex= "COLUMN_NAME")
{
    DataTable dsTablesData = DbDataHelper.GetCon().GetOleDbSchemaTable(gtype, new Object[] { null, null, tableName, null });
    List<Dictionary<string, string>> ditCol = new List<Dictionary<string, string>>() ;

    // 预分配List大小
    for (int i = 0; i < dsTablesData.DefaultView.Table.Rows.Count; i++)
    {
        ditCol.Add(new Dictionary<string, string> { { i.ToString(), i.ToString() } });
    }

    foreach (DataRow item in dsTablesData.DefaultView.Table.Rows)
    {
        int pos = Convert.ToInt32(item["ORDINAL_POSITION"]);
        int typeIndex = Convert.ToInt32(item["DATA_TYPE"]);

        // 假设 DBData.getInstance().GetColNameType(typeIndex) 能将数字类型码转换为字符串类型名
        ditCol[pos-1]= new Dictionary<string, string> { { item[itemIndex].ToString(), DBData.getInstance().GetColNameType(typeIndex) } };
    }

    return ditCol;
}

第3步:调用示例与从DataTable直接获取列名

完成上述封装后,可按以下逻辑执行:

// 1. 获取所有表名
DBData.getInstance()._tableNames = GetTablesName(OleDbSchemaGuid.Tables);

// 2. 遍历表名,获取每表的列信息
foreach (var tableName in DBData.getInstance()._tableNames)
{
    // 此处可根据实际需要处理 tmp 数据
    List<Dictionary<string, string>> tmp = GetColsName(OleDbSchemaGuid.Columns, tableName);
}

补充技巧:如果已经持有某个 DataTable 对象,无需再次查询数据库,可直接反射其 Columns 集合:

/// <summary>
/// 根据datatable获得列名
/// </summary>
public static List<string> GetColumnsByDataTable(DataTable dt)
{
    List<string> list = new List<string>;

    foreach (DataColumn item in dt.Columns)
    {
        list.Add(item.ColumnName);
    }

    return list;
} 

注意事项与排错

  • 权限问题:确保数据库连接字符串中的用户具有查看架构(Schema)的权限,否则可能返回空表或抛出异常。
  • 驱动差异:不同数据库(如 Access SQL Server via OleDB)对 GetOleDbSchemaTable 的支持程度略有不同。若返回结果为空,请检查 tableType 参数是否需要调整(例如某些驱动需传 MULTI_ROWSET 或其他特定值)。
  • 性能影响:频繁调用 Schema 查询会增加数据库负载,建议将结果缓存或使用静态反射工具替代运行时查询。

以上就是使用C#结合OleDb获取数据库中所有表名、列名的详细内容,更多关于C#操作数据库结构资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表