Dapper 是否在 Linq 操作之前从数据库请求一个完整的对象?

Does Dapper request a full object from the database prior to Linq operations?

我一直对 Dapper(或者其他 ORM)在与 LINQ 结合时如何处理对象检索感到好奇。

如果我有这样的class:

public static IEnumerable<SitePage> GetAll()
{
    using (IDbConnection cn = new SqlConnection(g.Global.CONX))
    {
        cn.Open();
        return cn.GetAll<SitePage>();
    }
}

然后我构建了一个这样的查询:

var result = SitePage.GetAll().Select(c=> new { c.id, c.PageUrl, c.ParentId });

我很好奇是否在后台拉入了整个记录集,包括所有其他列(可能包含非常大的 varchars),或者 Dapper 是否从该查询中理解仅拉入我请求的列sql 分贝?我意识到这有点新奇,但我想更好地理解 Dapper/LINQ 交互。

此处发布了一个类似的问题:selecting-specific-columns-using-linq-what-gets-transferred,但我不确定是否已得到完整回答。海报有 2 个问题,也没有使用我通常喜欢的 lambda 表达式。

这个问题的答案会让我大吃一惊(并且很可能会改变我编码的方式,因为我一直很谨慎并且觉得我通过显式 sql 编写了太多代码)。

Dapper 不会将您的 lambda 表达式转换为 SQL,因此在您的情况下,SQL 查询 Dapper 会生成 return 个 SitePage 的完整实例。

如果查看 Dapper 的 GetAll<T> 方法的签名,可以快速了解是否属于这种情况。因为它 returns IEnumerable<T>,这意味着它 returns 是 T 的集合,所以你之后使用的任何运算符 - 比如你的情况下的 Select -将应用于整个集合。简而言之,调用 GetAll<T>.

后,您将不再处于 Dapper 世界中

如果您过去使用过 fully-fledged ORM——我的意思是功能更多,不一定更好——比如 Entity Framework 或 NHibernate,您会注意到一些 API return IQueryable<T>,表示尚未执行的查询。因此,您在 IQueryable<T> 上使用的运算符,如 SelectWhere,实际上会修改查询。当您通过迭代查询或调用 ToListToArray 来实现查询时,ORM 会将您的查询表达式树转换为 SQL 并将该查询发送到数据库。