对来自dapper result的每个记录调用一个函数
本文关键字:调用 函数 一个 记录 dapper result | 更新日期: 2023-09-27 17:54:57
我试图在每个记录上调用一个函数,将设置一些字段值。当要对结果进行分页时,可以通过以下方式实现:
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;
}
当结果不打算被分页时,我的问题来了。我在第一个例子中的查询包括对列的分割,这就是为什么它都有效,但是我的下一个查询是一个简单的查询,例如Select Column1, Column2 FROM MyAwesomeTable
,它将返回所有行,列等…
问题是我仍然需要对返回的每个结果应用customAction。现在让我们想象一下,有几百万条记录返回的可能性(相信我,考虑到我的情况,这不是不现实的),因此我不想在每条记录之后再次循环并应用我的方法,我希望在dapper返回结果时应用该方法,就像在第一种情况下一样。
这是我尝试的:
public IDataWrapper GetNonPagedQuery<T>(string myQuery, object param, Action<T> customAction)
{
var obj = new DataWrapper ();
using (var oConn = CreateConnection(ConnectionString))
{
var list = oConn.Query<T>(myQuery, (e) =>
{
if (mapAction != null) customAction(e);
return e;
}, param).ToList();
obj.RowsFound = (IEnumerable<dynamic>)list;
obj.TotalRows = list.Count();
}
return obj;
}
我得到一个错误,上面的代码,它不能解决方法Query<T>(etc...
我理解这是因为它不存在。我在这里问的是,完成我正在努力做的事情的最好方法是什么?
我恐怕简短的回答是你不能这样做。
稍微长一点的答案是,在您的分页查询中,它本质上是是通过数据的第二次传递,因为Dapper做一些工作将每一行的数据转换为"T"的实例,然后它对"map"方法进行单独调用,您使用该方法调用"customAction"。
因此,这与执行简单的非分页"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;
}
如果你担心的是,你可能会加载许多,许多记录在非分页查询那么值得记住的是,所有的这些记录将被加载到内存一次;它们不会像对返回结果的枚举那样一次一个地从数据库中取出,这可能会对资源造成相当大的消耗(如果您讨论的数据太多,希望避免进行第二次枚举)。
必须是这种情况,因为SQL连接在GetNonPagedQuery返回时关闭,因此没有办法让调用者"按需"读取数据。如果您确实要处理大量数据,也许非分页查询不是最好的方法?
注意,在上面的代码中,"customAction"只会在枚举行时被调用,在GetNonPagedQuery返回之前不会触发所有的行。如果"customAction"可能是一个昂贵的操作,那么这可能对您有益。另一方面,如果您希望在GetNonPagedQuery返回之前为每个结果调用"customAction",那么您将需要在Cast
我不是分页查询或非分页查询方面的专家,但是如果有人希望对每一行应用操作,我已经根据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;
}
}
我这样用
var result = dmsConnection.QueryLazyWithActionAsync<CustomerResult>(sql, query, row =>
{
Console.WriteLine($"Querying for customer {row.FullName}");
});
是的,可能是:
请参阅Dapper文档中关于每行类型切换的部分。我怀疑(即没有尝试过它自己),它不会工作,如果你使用相同的系统按摩的结果,通过读取每一行,并显式处理它的格式。