C# 根据dapper结果对每条记录调用函数

C# 根据dapper结果对每条记录调用函数,c#,asp.net-mvc-5,dapper,C#,Asp.net Mvc 5,Dapper,我试图在每条记录上调用一个函数来设置一些字段值。如果要分页结果,则可通过以下方式实现: public IDataWrapper GetPagedQuery<T>(string myQuery, object param, Action<T> customAction) { var obj = new DataWrapper (); using (var oConn = CreateConnection(ConnectionString)) {

我试图在每条记录上调用一个函数来设置一些字段值。如果要分页结果,则可通过以下方式实现:

public IDataWrapper GetPagedQuery<T>(string myQuery, object param, Action<T> customAction)
{
    var obj = new DataWrapper ();
    using (var oConn = CreateConnection(ConnectionString))
    {
        TotalPages totalRows = null;
        var list = oConn.Query<T, TotalPages, T>(myQuery, (e, t) =>
        {
            totalRows = t;
            if (mapAction != null) customAction(e);
            return e;
        }, param, splitOn: "SplitOn");
        obj.RowsFound = (IEnumerable<dynamic>)list;
        obj.TotalRows = totalRows == null ? 0 : totalRows.TotalRows;
    }
    return obj;
}

我发现上面的代码有一个错误,它无法解析方法
查询(等等)。
我理解这是因为它不存在。我在这里问,什么是完成我试图做的事情的最佳方法?是否可以使用dapper进行处理。

我恐怕简短的回答是,你不能这样做

稍微长一点的答案是,在分页查询中,它本质上是第二次传递数据,因为Dapper做了一些工作,将每一行的数据转换为“T”的实例,然后它单独调用用于调用“customAction”的“map”方法

因此,这与执行一个简单的无页面“conn.Query”调用,然后通过后续过程来执行customAction之间没有什么区别。如下所示:

public IDataWrapper GetNonPagedQuery<T>(string myQuery, object param, Action<T> customAction)
{
    var obj = new DataWrapper();
    using (var oConn = CreateConnection(ConnectionString))
    {
        var results = oConn
            .Query<T>(myQuery)
            .ToList();
        obj.TotalRows = results.Count();
        obj.RowsFound = results
            .Select(value =>
            {
                customAction(value);
                return value;
            })
            .Cast<dynamic>();
    }
    return obj;
}
公共IDataWrapper GetNonPagedQuery(字符串myQuery、对象参数、操作customAction) { var obj=新的数据包装器(); 使用(var oConn=CreateConnection(ConnectionString)) { var结果=oConn .Query(myQuery) .ToList(); obj.TotalRows=results.Count(); obj.RowsFound=结果 .选择(值=> { 海关行动(价值); 返回值; }) .Cast(); } 返回obj; } 如果您担心在非分页查询中可能会加载很多记录,那么值得记住的是,所有这些记录都将一次加载到内存中;当您枚举返回的结果时,它们不会一次从数据库中提取出来,这可能会大大消耗资源(如果您谈论的数据太多,希望避免第二次枚举)

必须如此,因为SQL连接在GetNonPagedQuery返回时关闭,因此无法让它保持打开状态,以便调用者“按需”读取数据。如果您确实在处理大量数据,可能非分页查询不是最佳方法

请注意,在上面的代码中,“customAction”仅在您枚举行时调用,在GetNonPagedQuery返回之前不会全部激发。如果“customAction”可能是一个昂贵的操作,那么这可能对您有利。另一方面,如果您想要“customAction”如果要在GetNonPagedQuery返回之前为每个结果调用,则在Cast()之后还需要一个ToList()调用,这取决于哪个场景对您更有用。

是的,可能是:


我怀疑(我自己没有试过)如果您使用相同的系统通过读取每一行并显式处理结果,将结果转换为您想要的格式,那么它将不起作用。

我不擅长分页查询或非分页查询,但如果有人希望对每一行应用操作,我是根据gbjbaanb对Dapper文档的引用而提出的

public static async IAsyncEnumerable<T> QueryLazyWithActionAsync<T>(this DbConnection self, string sql, object query, Action<T> action)
{
    using var reader = await self.ExecuteReaderAsync(sql, query);
    var parser = reader.GetRowParser<T>();
    while (await reader.ReadAsync())
    {
        var row = parser(reader);
        action(row);
        yield return row;
    }
}
公共静态异步IAsyncEnumerable QueryLazyWithActionAsync(此数据库连接自身、字符串sql、对象查询、操作)
{
使用var reader=wait self.ExecuteReaderAsync(sql,查询);
var parser=reader.GetRowParser();
while(等待reader.ReadAsync())
{
var行=解析器(读取器);
行动(世界其他地区);
收益返回行;
}
}
我就是这样用的

var result = dmsConnection.QueryLazyWithActionAsync<CustomerResult>(sql, query, row =>
{
    Console.WriteLine($"Querying for customer {row.FullName}");
});
var result=dmsConnection.QueryLazyWithActionAsync(sql,查询,行=>
{
WriteLine($“查询客户{row.FullName}”);
});

您对SplitOn的理解是不正确的,它的目的是映射1-1个与分页无关的复杂实体,可以用于任何类型的查询。当前代码替换每个记录的TotalRows,这与Sql查询获取的重复值相同,但其本身并不是最佳用法,尽管您可以重复多次另一方面,对于任意数量的记录,dapper所做的所有处理都是在内存中后期获取数据,如果您已明确应用,则不必过度担心遍历内存中的数据Action@MrinalKamboj我相信我对SplitOn有很好的理解,你看不到的是我完整的SQL语句ght在解释问题中的这一部分以及由此产生的误解方面做得很糟糕。我想说的是,我的分页使用了拆分列,就像我们对查询进行分页一样,而不是分页有拆分。长话短说,第一个查询使用拆分,第二个不使用。很抱歉误解。理解我的观点d不同的是,您使用为SplitOn提供的Func来应用自定义操作,事实上,即使在SplitOn中,它也在填充重复值,这两者都是不正确的。它的印象是,当Dapper实际遍历内存中的集合时,它不需要遍历集合,因为它是Linq 2 objects提供程序。理想的方法是在任何地方删除SplitOn,使用QueryMultiple在一次调用中获得单独的结果,然后按照您已接受的响应中所示单独应用操作。我已经尝试了IDataReader.GetRowParser,它可以工作。我的用例是向Wpf UI报告进度。
var result = dmsConnection.QueryLazyWithActionAsync<CustomerResult>(sql, query, row =>
{
    Console.WriteLine($"Querying for customer {row.FullName}");
});