C# 读取数据库表结构工具设计与实现思路

 更新时间:2026年04月03日 11:05:03   作者:ytttr873  
本文介绍了基于C#和ADO.NET的数据库表结构读取工具,并详细阐述了实现步骤、关键技术点及扩展功能,该工具具备低侵入性和高扩展性,适用于开发调试、数据库文档生成等场景,感兴趣的朋友跟随小编一起看看吧

一、系统概述

读取数据库表结构是数据库管理、代码生成(如ORM模型)、数据迁移等场景的基础需求。本工具基于 C# 语言和 ADO.NET 框架,支持多数据库兼容(SQL Server、MySQL、PostgreSQL),通过查询数据库系统元数据(如INFORMATION_SCHEMA)获取表的列信息(名称、数据类型、约束)、主键/外键、索引等结构,输出为结构化数据(如DataTable、JSON)或可视化报告。工具具备低侵入性(无需数据库驱动额外配置)、高扩展性(支持自定义查询)特点,适用于开发调试、数据库文档生成等场景。

二、核心设计思路

2.1 元数据来源

不同数据库通过系统表/视图暴露元数据,核心查询对象包括:

  • 列信息INFORMATION_SCHEMA.COLUMNS(通用)、sys.columns(SQL Server)、information_schema.columns(MySQL/PostgreSQL)
  • 主键信息INFORMATION_SCHEMA.KEY_COLUMN_USAGE(通用)、sys.key_constraints(SQL Server)
  • 外键信息INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS(通用)
  • 索引信息sys.indexes(SQL Server)、pg_indexes(PostgreSQL)

2.2 多数据库兼容策略

通过抽象工厂模式封装不同数据库的查询逻辑,核心步骤:

  1. 根据数据库类型(如SQLServerMySQL)选择对应的连接字符串查询模板
  2. 使用DbProviderFactory创建通用数据库对象(DbConnectionDbCommand);
  3. 执行参数化查询,避免SQL注入。

三、实现步骤与代码

3.1 开发环境

  • 语言:C# 9.0+
  • 框架:.NET 6.0(跨平台)
  • 依赖System.Data.Common(通用ADO.NET)、数据库驱动(如Microsoft.Data.SqlClientMySqlConnector

3.2 核心类设计

3.2.1 数据库类型枚举

public enum DatabaseType
{
    SqlServer,   // SQL Server
    MySQL,       // MySQL
    PostgreSQL,  // PostgreSQL
    Oracle       // Oracle(预留)
}

3.2.2 表结构信息模型

// 列信息
public class ColumnInfo
{
    public string TableName { get; set; }    // 表名
    public string ColumnName { get; set; }   // 列名
    public string DataType { get; set; }     // 数据类型(如int、nvarchar(50))
    public int MaxLength { get; set; }       // 最大长度
    public bool IsNullable { get; set; }     // 是否允许NULL
    public string DefaultValue { get; set; } // 默认值
    public int OrdinalPosition { get; set; }  // 列顺序
}
// 主键信息
public class PrimaryKeyInfo
{
    public string TableName { get; set; }
    public string ColumnName { get; set; }
    public int KeyOrder { get; set; }  // 主键顺序(复合主键)
}
// 表结构汇总
public class TableSchema
{
    public string TableName { get; set; }
    public List<ColumnInfo> Columns { get; set; } = new();
    public List<PrimaryKeyInfo> PrimaryKeys { get; set; } = new();
}

3.3 核心功能实现

3.3.1 数据库连接与查询(通用方法)

using System.Data.Common;
using Microsoft.Data.SqlClient;  // SQL Server驱动
using MySqlConnector;            // MySQL驱动
public class DbSchemaReader
{
    private readonly string _connectionString;
    private readonly DatabaseType _dbType;
    public DbSchemaReader(string connectionString, DatabaseType dbType)
    {
        _connectionString = connectionString;
        _dbType = dbType;
    }
    // 创建数据库连接
    private DbConnection CreateConnection()
    {
        return _dbType switch
        {
            DatabaseType.SqlServer => new SqlConnection(_connectionString),
            DatabaseType.MySQL => new MySqlConnection(_connectionString),
            _ => throw new NotSupportedException($"不支持的数据库类型: {_dbType}")
        };
    }
    // 执行查询并返回DataTable
    public DataTable ExecuteQuery(string sql)
    {
        using var conn = CreateConnection();
        conn.Open();
        using var cmd = conn.CreateCommand();
        cmd.CommandText = sql;
        using var adapter = GetDataAdapter(cmd);
        var dt = new DataTable();
        adapter.Fill(dt);
        return dt;
    }
    // 获取数据库适配器(适配不同数据库)
    private DbDataAdapter GetDataAdapter(DbCommand cmd)
    {
        return _dbType switch
        {
            DatabaseType.SqlServer => new SqlDataAdapter((SqlCommand)cmd),
            DatabaseType.MySQL => new MySqlDataAdapter((MySqlCommand)cmd),
            _ => throw new NotSupportedException()
        };
    }
}

3.3.2 读取表列信息(以SQL Server为例)

// 获取指定表的所有列信息
public List<ColumnInfo> GetColumns(string tableName)
{
    string sql = @"
        SELECT 
            c.TABLE_NAME AS TableName,
            c.COLUMN_NAME AS ColumnName,
            c.DATA_TYPE AS DataType,
            c.CHARACTER_MAXIMUM_LENGTH AS MaxLength,
            CASE WHEN c.IS_NULLABLE = 'YES' THEN 1 ELSE 0 END AS IsNullable,
            c.COLUMN_DEFAULT AS DefaultValue,
            c.ORDINAL_POSITION AS OrdinalPosition
        FROM INFORMATION_SCHEMA.COLUMNS c
        WHERE c.TABLE_NAME = @TableName
        ORDER BY c.ORDINAL_POSITION";
    using var conn = CreateConnection();
    conn.Open();
    using var cmd = conn.CreateCommand();
    cmd.CommandText = sql;
    cmd.Parameters.Add(new SqlParameter("@TableName", tableName));
    using var reader = cmd.ExecuteReader();
    var columns = new List<ColumnInfo>();
    while (reader.Read())
    {
        columns.Add(new ColumnInfo
        {
            TableName = reader["TableName"].ToString(),
            ColumnName = reader["ColumnName"].ToString(),
            DataType = reader["DataType"].ToString(),
            MaxLength = reader["MaxLength"] == DBNull.Value ? 0 : Convert.ToInt32(reader["MaxLength"]),
            IsNullable = Convert.ToBoolean(reader["IsNullable"]),
            DefaultValue = reader["DefaultValue"]?.ToString(),
            OrdinalPosition = Convert.ToInt32(reader["OrdinalPosition"])
        });
    }
    return columns;
}

3.3.3 读取主键信息(通用方法)

// 获取指定表的主键列
public List<PrimaryKeyInfo> GetPrimaryKeys(string tableName)
{
    string sql = @"
        SELECT 
            kcu.TABLE_NAME AS TableName,
            kcu.COLUMN_NAME AS ColumnName,
            kcu.ORDINAL_POSITION AS KeyOrder
        FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
        JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc 
            ON kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
        WHERE tc.TABLE_NAME = @TableName 
            AND tc.CONSTRAINT_TYPE = 'PRIMARY KEY'
        ORDER BY kcu.ORDINAL_POSITION";
    // 执行查询(类似GetColumns方法,略)
    // ...
}

3.3.4 整合表结构(完整示例)

// 获取指定表的所有结构信息
public TableSchema GetTableSchema(string tableName)
{
    var schema = new TableSchema { TableName = tableName };
    schema.Columns = GetColumns(tableName);
    schema.PrimaryKeys = GetPrimaryKeys(tableName);
    return schema;
}

参考代码 C#-读取数据库表结构 www.youwenfan.com/contentcss/123124.html

四、关键技术点

4.1 多数据库适配

  • 连接字符串差异
    • SQL Server:"Server=.;Database=TestDB;User Id=sa;Password=123456;"
    • MySQL:"Server=localhost;Database=TestDB;Uid=root;Pwd=123456;"
  • 查询语法差异:部分数据库(如Oracle)的系统表名称不同,需调整SQL模板。

4.2 性能优化

  • 批量查询:通过INFORMATION_SCHEMA一次性获取所有表结构,避免多次查询;
  • 缓存机制:对频繁访问的表结构缓存结果(如用MemoryCache)。

4.3 异常处理

  • 连接失败:捕获DbException,提示“数据库连接失败,请检查连接字符串”;
  • 表不存在:查询前先判断表是否存在(如SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @TableName)。

五、扩展功能

5.1 可视化报告(JSON/HTML)

TableSchema对象序列化为JSON或HTML,示例:

// 序列化为JSON
var json = JsonSerializer.Serialize(schema, new JsonSerializerOptions { WriteIndented = true });
// 生成HTML表格
string html = $"<h1>{schema.TableName} 结构</h1><table border='1'>...";

5.2 代码生成(ORM模型)

根据表结构自动生成C#实体类:

// 生成实体类代码
string GenerateEntityClass(TableSchema schema)
{
    var sb = new StringBuilder();
    sb.AppendLine($"public class {schema.TableName}");
    sb.AppendLine("{");
    foreach (var col in schema.Columns)
    {
        string type = MapDbTypeToCSharp(col.DataType);
        sb.AppendLine($"    public {type} {col.ColumnName} {{ get; set; }}");
    }
    sb.AppendLine("}");
    return sb.ToString();
}
// 数据库类型映射C#类型
private string MapDbTypeToCSharp(string dbType)
{
    return dbType.ToLower() switch
    {
        "int" => "int",
        "nvarchar" => "string",
        "datetime" => "DateTime",
        _ => "object"
    };
}

六、总结

本工具通过ADO.NET和系统元数据查询实现了数据库表结构的读取,支持多数据库兼容和结构化输出。核心优势在于低侵入性(无需数据库特定API)和高扩展性(可添加索引、外键等查询)。代码模块化设计,便于集成至开发工具(如数据库文档生成器)或业务系统。

到此这篇关于C# 读取数据库表结构工具设计与实现思路的文章就介绍到这了,更多相关C# 读取数据库表结构内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C#实现高保真的Excel转PDF详解(无需 Office 环境)

    C#实现高保真的Excel转PDF详解(无需 Office 环境)

    在日常办公自动化或系统报表开发中,常常需要将 Excel 文件转换为 PDF 格式,本文将介绍如何使用 Spire.XLS for .NET 实现这一功能,希望对大家有所帮助
    2025-10-10
  • 浅析C#中ref与out参数传递的核心区别与实战指南

    浅析C#中ref与out参数传递的核心区别与实战指南

    这篇文章为大家系统梳理了C#中ref与out参数传递的核心区别与使用场景,ref用于双向传递,调用前必须初始化,方法内可读写,out用于单向输出,方法内必须赋值,调用前无需初始化,下面小编就和大家详细介绍一下吧
    2026-02-02
  • 同步调用和异步调用WebService

    同步调用和异步调用WebService

    本文给大家介绍webservice同步调用和异步调用,同步调用就是一个同步操作会阻塞整个当前的进程,直到这个操作完成才能执行下一段代码,异步调用不会阻塞启动操作的调用线程,调用程序必须通过轮流检测,或者等待完成信号来发现调用的完成。小伙伴们跟着小编一起学习
    2015-09-09
  • c#测试反射性能示例

    c#测试反射性能示例

    这篇文章主要介绍了c#测试反射性能示例,Activator.CreateInstance和AssemblyCreateInstance性能测试,需要的朋友可以参考下
    2014-03-03
  • C#实现将Excel表格转换为DataTable

    C#实现将Excel表格转换为DataTable

    在企业级开发中,Excel 与数据库 / 内存数据集的互转是高频需求,DataTable 作为.NET 中通用的内存数据结构,常被用于承接 Excel 数据进行后续处理,下面我们就来看看如何使用C#实现二者间的转换吧
    2026-01-01
  • c#多线程中Lock()关键字的用法小结

    c#多线程中Lock()关键字的用法小结

    本篇文章主要是对c#多线程中Lock()关键字的用法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2014-01-01
  • C# winform自定义翻页控件详解

    C# winform自定义翻页控件详解

    这篇文章主要为大家详细介绍了C# winform自定义翻页控件的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-09-09
  • C#实现图片加相框的方法

    C#实现图片加相框的方法

    这篇文章主要介绍了C#实现图片加相框的方法,涉及C#图片及图形绘制的相关技巧,需要的朋友可以参考下
    2016-02-02
  • C#泛型详解

    C#泛型详解

    本文详细讲解了C#中的泛型,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • DevExpress实现GridControl显示Gif动画的方法

    DevExpress实现GridControl显示Gif动画的方法

    这篇文章主要介绍了DevExpress实现GridControl显示Gif动画的方法,这是比较实用的方法,需要的朋友可以参考下
    2014-08-08

最新评论