You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C#中使用SQLite如何获取数据表对应的实体类类型?

问题分析

你这段代码的核心错误有两个:

  1. 类型比较完全错误:reader.GetType()拿到的是SqliteDataReader的类型,而typeof(T).GetType()拿到的是Type类型,两者永远不可能相等,这是根本进不了if判断的原因。
  2. 逻辑流程错误:当前reader读取的是sqlite_master中的表名,不是表的实际数据,你需要先拿到表名,再针对每个表名执行查询,读取对应表的数据。
解决方案

首先约定实体类名称和数据库表名一致(比如Product类对应Product表,Service类对应Service表),然后修改逻辑:先获取所有表名,遍历每个表名时判断对应哪个泛型类型,再查询该表的数据并映射到实体类。

修正后的代码

public static (List<T>, List<U>) ViewInventory<T, U>()
    where T : class, new()
    where U : class, new()
{
    List<T> tableDataT = new();
    List<U> tableDataU = new();
    string tTableName = typeof(T).Name; // 假设类名和表名一致
    string uTableName = typeof(U).Name;

    using (var connection = new SqliteConnection(connectionString))
    {
        connection.Open();

        // 第一步:获取所有表名
        using (var tableCmd = connection.CreateCommand())
        {
            tableCmd.CommandText = "SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY 1";
            using (var reader = tableCmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    string currentTableName = reader.GetString(0);

                    // 第二步:判断当前表对应哪个实体类,查询数据并映射
                    if (currentTableName.Equals(tTableName, StringComparison.OrdinalIgnoreCase))
                    {
                        tableDataT = LoadTableData<T>(connection);
                    }
                    else if (currentTableName.Equals(uTableName, StringComparison.OrdinalIgnoreCase))
                    {
                        tableDataU = LoadTableData<U>(connection);
                    }
                }
            }
        }

        return (tableDataT, tableDataU);
    }
}

// 通用方法:从指定连接加载指定表的数据并映射到实体
private static List<T> LoadTableData<T>(SqliteConnection connection) where T : class, new()
{
    List<T> dataList = new();
    string tableName = typeof(T).Name;

    using (var cmd = connection.CreateCommand())
    {
        cmd.CommandText = $"SELECT * FROM {tableName}";
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                T model = new();
                foreach (var prop in typeof(T).GetProperties())
                {
                    // 处理字段值为DBNull的情况
                    object value = reader[prop.Name] == DBNull.Value ? null : reader[prop.Name];
                    prop.SetValue(model, value);
                }
                dataList.Add(model);
            }
        }
    }

    return dataList;
}

关键改进点

  • 用表名和实体类名的对应关系替代错误的类型比较,解决了判断逻辑失效的问题。
  • 提取了通用的LoadTableData方法,避免重复代码,同时实现了从DataReader到实体类的映射。
  • 处理了数据库字段值为DBNull的情况,避免赋值时出现异常。

额外说明

如果你的实体类名和表名不一致,可以手动指定表名,比如给泛型方法添加参数:

public static (List<T>, List<U>) ViewInventory<T, U>(string tTableName, string uTableName)
    where T : class, new()
    where U : class, new()
{
    // 后续逻辑用传入的tTableName和uTableName替代typeof(T).Name即可
}

内容的提问来源于stack exchange,提问作者Emil Uppenberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 21:13:30