如何用T-SQL2000与C#实现按ID分组返回RootObj列表
没问题,我帮你一步步解决这个问题——从数据库存储过程的编写,到C#里把查询结果组装成你要的RootObj列表,都给你讲清楚:
一、编写数据库存储过程
核心思路是按table1_id分组,把对应的table2_id聚合拼接成一个字符串,这样一次查询就能拿到每个id对应的所有info项。这里分两种情况适配不同的SQL Server版本:
1. 适配SQL Server 2017及以上(用STRING_AGG函数)
这个版本支持原生的字符串聚合函数,写法非常简洁:
CREATE PROCEDURE GetRootObjList AS BEGIN -- 禁止返回影响行数,避免干扰结果 SET NOCOUNT ON; SELECT table1_id AS Id, -- 用逗号分隔拼接table2_id,你可以换成其他不会出现在数据里的字符 STRING_AGG(table2_id, ',') AS InfoListStr FROM table1_table2 GROUP BY table1_id ORDER BY table1_id; END
2. 适配旧版SQL Server(用FOR XML PATH拼接)
如果你的SQL Server版本低于2017,就用这种兼容写法:
CREATE PROCEDURE GetRootObjList AS BEGIN SET NOCOUNT ON; SELECT t1.table1_id AS Id, -- 拼接table2_id并去掉开头的逗号 STUFF( (SELECT ',' + t2.table2_id FROM table1_table2 t2 WHERE t2.table1_id = t1.table1_id FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '' ) AS InfoListStr FROM table1_table2 t1 GROUP BY t1.table1_id ORDER BY t1.table1_id; END
二、C#代码组装RootObj列表
首先先定义你的RootObj类:
public class RootObj { public int Id { get; set; } public List<string> InfoList { get; set; } = new List<string>(); }
下面提供两种常用的实现方式,你可以根据项目情况选择:
1. 原生ADO.NET实现
不需要额外依赖,适合基础场景:
public List<RootObj> GetRootObjList() { var rootObjList = new List<RootObj>(); // 替换成你的数据库连接字符串 string connectionString = "Server=你的服务器;Database=你的库名;Trusted_Connection=True;"; using (SqlConnection conn = new SqlConnection(connectionString)) { conn.Open(); using (SqlCommand cmd = new SqlCommand("GetRootObjList", conn)) { cmd.CommandType = CommandType.StoredProcedure; using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { // 读取字段值 int id = reader.GetInt32(reader.GetOrdinal("Id")); string infoStr = reader.IsDBNull(reader.GetOrdinal("InfoListStr")) ? string.Empty : reader.GetString(reader.GetOrdinal("InfoListStr")); // 拆分字符串为列表 var infoList = string.IsNullOrEmpty(infoStr) ? new List<string>() : infoStr.Split(',').ToList(); rootObjList.Add(new RootObj { Id = id, InfoList = infoList }); } } } } return rootObjList; }
2. Dapper实现(更简洁高效)
如果你的项目已经用了Dapper(需要先安装Dapper NuGet包),代码会更简洁:
using Dapper; public List<RootObj> GetRootObjListWithDapper() { string connectionString = "Server=你的服务器;Database=你的库名;Trusted_Connection=True;"; using (var conn = new SqlConnection(connectionString)) { conn.Open(); // 先查询出临时的匿名类型结果,再映射成RootObj var result = conn.Query<(int Id, string InfoListStr)>( "GetRootObjList", commandType: CommandType.StoredProcedure) .Select(item => new RootObj { Id = item.Id, InfoList = string.IsNullOrEmpty(item.InfoListStr) ? new List<string>() : item.InfoListStr.Split(',').ToList() }) .ToList(); return result; } }
注意事项
如果你的table2_id里可能包含逗号,记得把存储过程和C#代码里的分隔符换成其他不会出现在数据里的字符(比如|、#等),避免拆分出错。
内容的提问来源于stack exchange,提问作者Jorge Moura
相关产品推荐
相关产品推荐

