如何将PetaPocoHelper的ExecuteReader转为List[C#]?存储过程数据存List异常
我来帮你搞定这个问题!看起来你在从存储过程获取多结果集的时候,只把第一组数据存进List了,剩下的数据集完全没被处理对吧?先把你提到的相关内容整理清楚,再一步步解决~
1. 你的现有代码与结果
1.1 存储过程示例
-- 假设你的存储过程结构如下(可根据实际场景调整) CREATE PROCEDURE GetMultiDatasetData AS BEGIN -- 第一个结果集:活跃用户信息 SELECT UserId, UserName FROM Users WHERE IsActive = 1; -- 第二个结果集:近1个月订单记录 SELECT OrderId, UserId, OrderDate FROM Orders WHERE OrderDate >= DATEADD(month, -1, GETDATE()); END
1.2 C# List填充实体类
// 用户信息实体 public class UserInfo { public int UserId { get; set; } public string UserName { get; set; } } // 订单信息实体 public class OrderInfo { public int OrderId { get; set; } public int UserId { get; set; } public DateTime OrderDate { get; set; } } // 多结果集封装容器 public class MultiDataResult { public List<UserInfo> Users { get; set; } = new List<UserInfo>(); public List<OrderInfo> Orders { get; set; } = new List<OrderInfo>(); }
1.3 有问题的C#业务代码
public MultiDataResult GetDataFromStoredProc() { var result = new MultiDataResult(); string connectionString = "你的数据库连接字符串"; using (SqlConnection conn = new SqlConnection(connectionString)) { using (SqlCommand cmd = new SqlCommand("GetMultiDatasetData", conn)) { cmd.CommandType = CommandType.StoredProcedure; conn.Open(); SqlDataReader reader = cmd.ExecuteReader(); // 仅读取了第一个结果集 while (reader.Read()) { result.Users.Add(new UserInfo { UserId = (int)reader["UserId"], UserName = reader["UserName"].ToString() }); } // 完全没处理第二个结果集! reader.Close(); } } return result; }
1.4 当前ReturnJSON返回结果
{ "Users": [ {"UserId": 1, "UserName": "Alice"}, {"UserId": 2, "UserName": "Bob"} ], "Orders": [] }
1.5 SQL Server Management Studio执行结果
执行存储过程后,SSMS显示两组结果:
- 第一组:2条活跃用户记录
- 第二组:5条近1个月的订单记录
1.6 期望的JSON返回格式
{ "Users": [ {"UserId": 1, "UserName": "Alice"}, {"UserId": 2, "UserName": "Bob"} ], "Orders": [ {"OrderId": 101, "UserId": 1, "OrderDate": "2024-05-01T00:00:00"}, {"OrderId": 102, "UserId": 2, "OrderDate": "2024-05-05T00:00:00"}, {"OrderId": 103, "UserId": 1, "OrderDate": "2024-05-10T00:00:00"}, {"OrderId": 104, "UserId": 2, "OrderDate": "2024-05-15T00:00:00"}, {"OrderId": 105, "UserId": 1, "OrderDate": "2024-05-20T00:00:00"} ] }
2. 问题根因
你的代码只处理了第一个结果集,没有调用SqlDataReader.NextResult()方法切换到下一个结果集,导致后续数据集的内容完全没被读取和存入List。
3. 修复方案:处理多结果集
修改业务代码,读完第一个结果集后调用NextResult()切换,再读取第二个结果集:
public MultiDataResult GetDataFromStoredProc() { var result = new MultiDataResult(); string connectionString = "你的数据库连接字符串"; using (SqlConnection conn = new SqlConnection(connectionString)) { using (SqlCommand cmd = new SqlCommand("GetMultiDatasetData", conn)) { cmd.CommandType = CommandType.StoredProcedure; conn.Open(); // 用using包裹reader,自动释放资源,无需手动Close using (SqlDataReader reader = cmd.ExecuteReader()) { // 读取第一个结果集:用户数据 while (reader.Read()) { result.Users.Add(new UserInfo { UserId = (int)reader["UserId"], UserName = reader["UserName"].ToString() }); } // 切换到第二个结果集,成功切换后读取订单数据 if (reader.NextResult()) { while (reader.Read()) { result.Orders.Add(new OrderInfo { OrderId = (int)reader["OrderId"], UserId = (int)reader["UserId"], OrderDate = (DateTime)reader["OrderDate"] }); } } } } } return result; }
4. 额外优化建议
- 自动处理多结果集循环:如果存储过程返回3个及以上结果集,可以用循环遍历所有结果集:
do { // 可通过reader.GetSchemaTable()获取列信息,判断当前结果集对应哪个实体类 // 比如根据列名判断是用户还是订单,再填充对应List } while (reader.NextResult());
- 用ORM简化代码:推荐使用Dapper框架,它的
QueryMultiple()方法可以一键读取多结果集,代码更简洁:
using (var multi = conn.QueryMultiple("GetMultiDatasetData", commandType: CommandType.StoredProcedure)) { var users = multi.Read<UserInfo>().ToList(); var orders = multi.Read<OrderInfo>().ToList(); return new MultiDataResult { Users = users, Orders = orders }; }
内容的提问来源于stack exchange,提问作者Carlos Miranda
相关产品推荐
相关产品推荐

