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}");
});