You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:51:41