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

C#编写动态通用数据库表加载方法如何返回指定类型List集合

C# Dapper 通用表查询实现方案

你当前用的是Dapper作为ORM,它本身已经提供了完整的动态查询支持,不需要自己实现泛型反射逻辑,针对你的问题分场景实现即可:


方案1:泛型实现(优先推荐,类型安全无开销)

你之前写的Class class是Java的传参逻辑,C#直接用泛型方法就能解决,不需要额外传Type参数,编译期即可做类型校验:

using System.Text.RegularExpressions;
using System.Data;
using Dapper;
using Microsoft.Data.Sqlite; // 注意新版SQLite用这个包,旧System.Data.SQLite也兼容

public static List<T> LoadTable<T>(string tableName)
{
    using (IDbConnection cnn = new SqliteConnection(LoadConnectionString()))
    {
        // 必须校验表名!表名无法用SQL参数化,直接拼接有注入风险
        if (!Regex.IsMatch(tableName, @"^[a-zA-Z0-9_]+$"))
            throw new ArgumentException("非法表名", nameof(tableName));
        
        var result = cnn.Query<T>($"select * from {tableName}");
        return result.ToList();
    }
}

调用方式非常简单,直接指定实体类类型即可:

// 假设User是和User表字段一一对应的实体类
List<User> userList = LoadTable<User>("User");

方案2:运行时传Type的非泛型实现

如果你的实体类型是运行时动态获取的(比如通过反射、配置读取拿到的Type,写代码时无法确定具体类型),直接用Dapper提供的非泛型Query重载即可,不需要自己构造泛型方法:

public static List<object> LoadTable(string tableName, Type entityType)
{
    using (IDbConnection cnn = new SqliteConnection(LoadConnectionString()))
    {
        if (!Regex.IsMatch(tableName, @"^[a-zA-Z0-9_]+$"))
            throw new ArgumentException("非法表名", nameof(tableName));
        
        // 第一个参数传入实体Type即可
        var result = cnn.Query(entityType, $"select * from {tableName}");
        return result.ToList();
    }
}

调用示例:

Type entityType = Assembly.GetExecutingAssembly().GetType("MyNamespace.User");
List<object> userList = LoadTable("User", entityType);

关于List转换失败的问题

Dapper原生支持dynamic动态类型查询,你之前转换失败是因为用了强类型泛型查询后再强制转dynamic,完全不需要这么做,直接调用无泛型参数的Query方法,默认返回的就是IEnumerable<dynamic>:

public static List<dynamic> LoadTableDynamic(string tableName)
{
    using (IDbConnection cnn = new SqliteConnection(LoadConnectionString()))
    {
        if (!Regex.IsMatch(tableName, @"^[a-zA-Z0-9_]+$"))
            throw new ArgumentException("非法表名", nameof(tableName));
        
        var result = cnn.Query($"select * from {tableName}");
        return result.ToList();
    }
}

返回的动态对象可以直接访问字段属性,不需要做任何类型转换,适合快速开发、不需要强类型校验的场景。


重要提醒

表名无法通过SQL参数化传参,绝对不能把前端传入、未校验的内容直接拼接到SQL语句里,除了正则校验,更安全的做法是维护一个允许查询的表名白名单,匹配通过再执行查询,避免SQL注入风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 21:30:42