Dapper 从类型强类型集合

本文关键字:集合 强类型 类型 Dapper | 更新日期: 2023-09-27 17:55:50

在我的应用程序中,我使用Dapper访问数据库。

我有以下示例代码:

public IEnumerable GetByParentId(Type childType, string table) 
{
    IDbConnection _connection = _dbProvider.GetConnection();
    var _sqlString = "select * from " + table;
    IEnumerable _ret = _connection.Query(_sqlString).ToList(); 
    //return IEnumerable<Dapper.SqlMapper.FastExpando> 
    return _ret;
}

是否可以将FastExpando项目投射到我的childType或强制 Dapper 返回强类型集合?

无法更改我的方法签名!

Dapper 从类型强类型集合

您可以通过反射调用 Query 方法,并提供 childType 的通用 TItem 参数。然后,Dapper 将返回 IEnumerable,您将能够投射它。此外,您可以分叉 Dapper(它不是很大)并制作一个非常简单的 Query 重载,这将包含 (Type childType) 参数并在其中调用适当的方法。

您面临的是 C# 在使用泛型时的问题。作为静态类型语言,C# 不适合使用动态类型。如果你想动态工作,你总是以反思告终。

下面是如何使用类型参数调用查询方法的示例。您可能需要稍微更正一下:

    public IEnumerable GetByParentId(Type childType, string table)
    {
        IDbConnection _connection = _dbProvider.GetConnection();
        var _sqlString = "select * from " + table;
        var t = typeof(SqlMapper);
        var genericQuery = t.GetMethods().Where(x => x.Name == "Query" && x.GetGenericArguments().Length == 1).First(); // You can cache this object.
        var concreteQuery = genericQuery.MakeGenericMethod(childType); // you can also keep a dictionary of these, for speed.
        var _ret = (IEnumerable)concreteQuery.Invoke(null, new object[] { _connection, _sqlString });
        return _ret;
    }

附加:

另外,我在这里看到了一个更普遍的设计问题。您想动态指定类型,但随后想要获取静态类型的对象,您将能够强制转换(我假设是静态的,或者您想继续反射?然后。。。为什么要首先创建动态界面?你说,你不能改变界面,但这看起来有点愚蠢。似乎所有上下文都是静态类型的,但是由于某种原因,您有一个动态类型化的方法。如果您在编译时(或通过运行时中的泛型参数)知道类型,那么您应该简单地将方法更改为如下所示:

    public IEnumerable<T> GetByParentId<T>(string table)
    {
        IDbConnection _connection = _dbProvider.GetConnection();
        var _sqlString = "select * from " + table;
        var _ret = _connection.Query<T>(_sqlString);
        return _ret;
    }