在C#中使用SQLite如何获取数据表对应的实体类类型?
问题分析
你这段代码的核心错误有两个:
- 类型比较完全错误:
reader.GetType()拿到的是SqliteDataReader的类型,而typeof(T).GetType()拿到的是Type类型,两者永远不可能相等,这是根本进不了if判断的原因。 - 逻辑流程错误:当前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
相关产品推荐
相关产品推荐

