如何使用Dapper批量执行Stored Procedure且无需循环调用Execute方法
问题原因分析
- 第一次编写的代码问题:你在循环中重复往同一个
DynamicParameters对象中添加同名参数,后续添加的参数会直接覆盖之前的同名参数,最终queryParameters中仅保留最后一条Person记录的参数值,因此仅最后一条数据被写入数据库。 - 第二次直接传入Person数组报错的问题:存储过程定义的参数名为
@id、@first_name、@last_name,但Person类的属性名为Id、FirstName、LastName,命名规则不匹配,Dapper自动映射时无法找到对应参数值,因此抛出参数不匹配错误。
正确实现方案
Dapper的Execute方法原生支持传入可枚举类型的参数集合,会自动遍历集合中的每个元素分别执行存储过程,无需手动将Execute放入循环中,你可以选择以下两种方案实现:
方案1:使用匹配参数名的匿名类集合(推荐,代码更简洁)
直接将Person集合转换为属性名和存储过程参数名完全匹配的匿名类集合,传入Execute方法即可:
public static int SaveData3() { var list = new List<Person>(); var p1 = new Person() { Id = 20, FirstName = "Michiel", LastName = "De Ruyter" }; var p2 = new Person() { Id = 21, FirstName = "Jacob", LastName = "Jakobsson" }; list.Add(p1); list.Add(p2); // 转换为属性名和存储过程参数名匹配的匿名类集合 var paramList = list.Select(p => new { id = p.Id, first_name = p.FirstName, last_name = p.LastName }).ToList(); using (IDbConnection connection = new OracleConnection(GetConnectionString())) { try { var affectedRows = connection.Execute("kwc_test_person_procedure", paramList, commandType: CommandType.StoredProcedure ); Log.Information("Executed procedure to store data. Rows affected: {0}", affectedRows); return affectedRows; } catch (Exception ex) { Log.Error(ex.Message); Log.Error(ex.StackTrace); throw; } } }
方案2:使用DynamicParameters集合
如果需要用到DynamicParameters的特殊能力(如指定参数类型、添加输出参数),可以构造DynamicParameters集合传入:
public static int SaveData3() { var list = new List<Person>(); var p1 = new Person() { Id = 20, FirstName = "Michiel", LastName = "De Ruyter" }; var p2 = new Person() { Id = 21, FirstName = "Jacob", LastName = "Jakobsson" }; list.Add(p1); list.Add(p2); var paramList = new List<DynamicParameters>(); foreach (var item in list) { var queryParameters = new DynamicParameters(); queryParameters.Add("@id", item.Id); queryParameters.Add("@first_name", item.FirstName); queryParameters.Add("@last_name", item.LastName); paramList.Add(queryParameters); } using (IDbConnection connection = new OracleConnection(GetConnectionString())) { try { var affectedRows = connection.Execute("kwc_test_person_procedure", paramList, commandType: CommandType.StoredProcedure ); Log.Information("Executed procedure to store data. Rows affected: {0}", affectedRows); return affectedRows; } catch (Exception ex) { Log.Error(ex.Message); Log.Error(ex.StackTrace); throw; } } }
两种方案执行后返回的受影响行数等于你传入的Person集合长度,所有数据都会正常写入数据库。
内容的提问来源于stack exchange,提问作者KWC
相关产品推荐
相关产品推荐

