调用MySQL返回多表数据的存储过程时C#无法获取完整内容的问题咨询
现有实现的疏漏点
- 重复执行存储过程:代码中先调用
ExecuteReader()执行了一次存储过程,紧接着又调用ExecuteNonQuery()第二次执行存储过程,不仅冗余还会导致第一次返回的结果集读取异常 - 未处理多结果集:你的存储过程一共返回5个独立的结果集对应5张表,
MySqlDataReader默认只会停留在第一个结果集,需要主动调用NextResult()方法才能切换到下一个结果集 - 提前终止读取:代码中读取到第一个结果集的第一行第一列的值后就直接return返回,既没有遍历当前表的所有行,也没有读取后续其他表的结果
- 异步使用不规范:方法声明为异步
async Task但全程使用同步方法,没有用到异步IO能力;同时未对MySqlConnection、MySqlCommand、MySqlDataReader等实现了IDisposable的对象做资源释放,容易引发数据库连接泄漏 - 返回结构不合理:当前仅返回单个字符串,完全无法承载5张表的全量数据,需要定义对应结构存储多张表的内容
修复方案
你的存储过程本身逻辑没有问题,无需修改,仅调整C#调用逻辑即可:
- 先定义承载返回数据的实体结构
public class FormListData { public List<MealType> MealTypes { get; set; } = new(); public List<RoomBedType> RoomBedTypes { get; set; } = new(); public List<RoomCoolingType> RoomCoolingTypes { get; set; } = new(); public List<RoomRent> RoomRents { get; set; } = new(); public List<RoomType> RoomTypes { get; set; } = new(); } // 以下是各表对应的实体类示例,可根据实际表结构调整字段 public class MealType { public int Id { get; set; } public string Name { get; set; } // 补充其他表字段 } // RoomBedType、RoomCoolingType、RoomRent、RoomType实体类按表结构自行补充
- 修正后的调用方法
public async Task<object> GetFormListDetails() { try { var result = new FormListData(); // using自动释放资源,无需手动调用Close using var con = new MySqlConnection(@"Server=Localhost;Database=HotelManagement;Uid=root;Pwd=Onkar@123;"); using var cmd = new MySqlCommand("GetFormListData", con); cmd.CommandType = CommandType.StoredProcedure; await con.OpenAsync(); using var reader = await cmd.ExecuteReaderAsync(); // 读取第一个结果集 MealType while (await reader.ReadAsync()) { result.MealTypes.Add(new MealType { Id = reader.GetInt32("id"), Name = reader.GetString("name") // 赋值其他字段 }); } // 切换到第二个结果集 RoomBedType await reader.NextResultAsync(); while (await reader.ReadAsync()) { result.RoomBedTypes.Add(new RoomBedType { // 按字段赋值 }); } // 切换到第三个结果集 RoomCoolingType await reader.NextResultAsync(); while (await reader.ReadAsync()) { result.RoomCoolingTypes.Add(new RoomCoolingType { // 按字段赋值 }); } // 切换到第四个结果集 RoomRent await reader.NextResultAsync(); while (await reader.ReadAsync()) { result.RoomRents.Add(new RoomRent { // 按字段赋值 }); } // 切换到第五个结果集 RoomType await reader.NextResultAsync(); while (await reader.ReadAsync()) { result.RoomTypes.Add(new RoomType { // 按字段赋值 }); } return new ResponseModel(ResponseCode.OK, "数据获取成功", result); } catch (Exception ex) { return new ResponseModel(ResponseCode.Error, ex.Message, null); } }
可选补充信息(如果调整后仍有问题可提供以下内容进一步排查)
- 各业务表的具体表结构
- 你期望的接口返回数据格式
- 调用时的具体报错信息或异常堆栈
内容的提问来源于stack exchange,提问作者Onkar Nirhali
相关产品推荐
相关产品推荐

