如何将SQL存储过程多结果集映射到C# View Model类
解决SQL多结果集映射到C# ViewModel的问题
嘿,我来帮你搞定这个多结果集映射的问题!你当前用的Database.SqlQuery<T>方法只能处理单个结果集,而你的存储过程返回了多个结果集(对应ViewModel里的total值、大洲统计列表和国家统计列表),所以得换一种方式手动读取每个结果集。下面是具体的实现步骤:
1. 确保子模型类与存储过程返回字段匹配
首先,你需要明确ContinentByPercentage和CountryByMembers的字段定义,要和存储过程返回的列名完全对应(大小写敏感,除非数据库配置了不区分)。比如:
public class ContinentByPercentage { public string ContinentName { get; set; } // 替换成存储过程返回的实际列名 public decimal Percentage { get; set; } // 其他对应字段,比如MemberCount等 } public class CountryByMembers { public string CountryName { get; set; } // 替换成存储过程返回的实际列名 public int TotalMembers { get; set; } // 其他对应字段 }
2. 手动读取多结果集的实现代码
我们需要直接使用DbConnection和DbDataReader来依次读取每个结果集,代码如下:
// 初始化目标ViewModel var memberStats = new MemberStatsByTopCountryViewModel(); using (var connection = Database.Connection) { // 确保连接处于打开状态 if (connection.State != ConnectionState.Open) connection.Open(); using (var command = connection.CreateCommand()) { command.CommandText = "sp_members"; command.CommandType = CommandType.StoredProcedure; // 执行存储过程并获取数据读取器 using (var reader = command.ExecuteReader()) { // 读取第一个结果集:Total成员数(单行单列) if (reader.Read()) { // 用GetOrdinal获取列索引,避免列顺序变化导致的错误 memberStats.total = reader.GetInt32(reader.GetOrdinal("Total")); } // 切换到第二个结果集:大洲占比列表 reader.NextResult(); var continentList = new List<ContinentByPercentage>(); while (reader.Read()) { continentList.Add(new ContinentByPercentage { ContinentName = reader.GetString(reader.GetOrdinal("ContinentName")), Percentage = reader.GetDecimal(reader.GetOrdinal("Percentage")) // 映射其他字段 }); } memberStats.continentByPercentage = continentList; // 切换到第三个结果集:国家成员数列表 reader.NextResult(); var countryList = new List<CountryByMembers>(); while (reader.Read()) { countryList.Add(new CountryByMembers { CountryName = reader.GetString(reader.GetOrdinal("CountryName")), TotalMembers = reader.GetInt32(reader.GetOrdinal("TotalMembers")) // 映射其他字段 }); } memberStats.countrybyMembers = countryList; } } } // 现在memberStats就包含了所有结果集的数据
关键注意事项
- 列名匹配:必须确保模型类的属性名和存储过程返回的列名完全一致,或者通过
GetOrdinal指定正确的列索引(推荐后者,更稳定)。 - 资源释放:所有
DbConnection、DbCommand和DbDataReader都要用using语句包裹,确保资源自动释放。 - EF版本兼容:如果是EF Core,代码略有不同,需要用
Database.GetDbConnection()来获取底层连接,但核心逻辑一致。
内容的提问来源于stack exchange,提问作者Arun kumar
相关产品推荐
相关产品推荐

