ASP.NET Core 3.1中能否通过Dapper同时执行更新与查询操作?
当然可以合并这两个操作!
Dapper完全支持在同一个数据库批处理中执行更新语句和查询语句,这样做能减少数据库往返次数,确实能提升性能——毕竟两次请求变成一次,省去了网络开销和数据库连接的额外消耗。
优化方案:合并更新与统计查询
首先,我们可以把你的两个操作合并成一段SQL,甚至可以把原来的两个COUNT查询合并成一个(减少一次表扫描,更高效)。这里用CASE WHEN来一次性统计点赞和点踩的数量:
-- 先执行更新操作 UPDATE likes AS L SET L.isLike = @isLikeSQL WHERE L.ItemId = @ItemIdSQL AND L.Ip = @IpSQL; -- 再执行合并统计查询 SELECT SUM(CASE WHEN isLike = 1 THEN 1 ELSE 0 END) AS NumberOfLikes, SUM(CASE WHEN isLike = 0 THEN 1 ELSE 0 END) AS NumberOfDislikes FROM likes WHERE ItemId = @ItemIdSQL;
对应的Dapper代码实现
用QueryMultipleAsync就可以处理这段SQL——它不仅支持多查询,也能处理包含更新/插入/删除语句的批处理,只要后面有SELECT返回结果集即可:
// 注意修正你原代码里的参数笔误:senderpSQL → IpSQL var parameters = new { ItemIdSQL = ItemId, IpSQL = Ip, isLikeSQL = isLike }; string sql = @" UPDATE likes AS L SET L.isLike = @isLikeSQL WHERE L.ItemId = @ItemIdSQL AND L.Ip = @IpSQL; SELECT SUM(CASE WHEN isLike = 1 THEN 1 ELSE 0 END) AS NumberOfLikes, SUM(CASE WHEN isLike = 0 THEN 1 ELSE 0 END) AS NumberOfDislikes FROM likes WHERE ItemId = @ItemIdSQL;"; using (var data = await dbConnection.QueryMultipleAsync(sql, parameters)) { // 第一个语句是UPDATE,没有结果集,直接读取第二个查询的统计结果 var countResult = data.Read<(int NumberOfLikes, int NumberOfDislikes)>().FirstOrDefault(); numberOfLikes = countResult.NumberOfLikes; numberOfDislikes = countResult.NumberOfDislikes; }
额外进阶:获取更新受影响行数
如果你需要知道这次更新操作影响了多少行数据(比如判断用户之前是否已经点赞/点踩过),可以在UPDATE后加一行获取受影响行数的语句(不同数据库语法略有差异):
- SQL Server:
SELECT @@ROWCOUNT; - MySQL:
SELECT ROW_COUNT(); - PostgreSQL:
GET DIAGNOSTICS row_count = ROW_COUNT; SELECT row_count;
以SQL Server为例,修改后的SQL:
UPDATE likes AS L SET L.isLike = @isLikeSQL WHERE L.ItemId = @ItemIdSQL AND L.Ip = @IpSQL; SELECT @@ROWCOUNT; -- 获取更新受影响的行数 SELECT SUM(CASE WHEN isLike = 1 THEN 1 ELSE 0 END) AS NumberOfLikes, SUM(CASE WHEN isLike = 0 THEN 1 ELSE 0 END) AS NumberOfDislikes FROM likes WHERE ItemId = @ItemIdSQL;
对应的代码:
using (var data = await dbConnection.QueryMultipleAsync(sql, parameters)) { int rowsAffected = data.Read<int>().FirstOrDefault(); var countResult = data.Read<(int NumberOfLikes, int NumberOfDislikes)>().FirstOrDefault(); // 可以根据rowsAffected判断是否是首次操作:比如0表示用户之前没有该记录 if (rowsAffected == 0) { // 可选逻辑:如果用户没有点赞/点踩记录,可能需要插入一条新记录? } numberOfLikes = countResult.NumberOfLikes; numberOfDislikes = countResult.NumberOfDislikes; }
注意事项
- 确保你的数据库支持批处理SQL(主流数据库如SQL Server、MySQL、PostgreSQL都支持);
- 如果你需要严格保证更新和查询的一致性(比如高并发场景),可以在操作外面加上事务:
using (var transaction = await dbConnection.BeginTransactionAsync()),然后把transaction传给QueryMultipleAsync的参数; - 原代码里的参数名
senderpSQL应该是笔误,改成了IpSQL,注意对应上参数名。
内容的提问来源于stack exchange,提问作者ehsan_kabiri_33
相关产品推荐
相关产品推荐

