C#中多表关联绑定GridView 如何避免B列值重复
解决GridView绑定多表关联数据时避免B列重复的问题
嘿,这个场景我之前踩过坑!当A作为主表,和B是1对1关联、和C是1对多关联的时候,多表查询出来的结果集里,B的字段肯定会跟着C的每条记录重复显示,绑定到GridView后就会显得乱糟糟的。下面给你几个实用的解决思路,按需挑选就行:
1. 从SQL查询层面处理(最推荐)
直接让返回的结果集里,同一A_no对应的B字段只在第一行显示,剩下的行留空。这里可以用窗口函数ROW_NUMBER()来实现,非常高效:
SELECT A.A_no, -- 同一A_no分组下,仅第一行显示B的内容,其余行留空 CASE WHEN ROW_NUMBER() OVER(PARTITION BY A.A_no ORDER BY C.C_no) = 1 THEN B.B_name ELSE '' END AS B_name, C.C_name, -- 按需添加其他字段 FROM A LEFT JOIN B ON A.A_no = B.A_no LEFT JOIN C ON A.A_no = C.A_no ORDER BY A.A_no, C.C_no
原理很简单:用PARTITION BY A.A_no把同一主表记录的关联数据分组,ROW_NUMBER()给每组内的行编号,然后只在第一行保留B的内容,其他行置空。这样GridView里同一A_no的B列就只有第一行有值,不会重复显示。
如果A和B是1对多的关系(比如一个A对应多个B),那可以把同一A_no的B字段合并成一个字符串,避免重复:
SELECT A.A_no, -- 合并同一A_no下的所有B名称为逗号分隔的字符串 STUFF((SELECT ', ' + B.B_name FROM B WHERE B.A_no = A.A_no FOR XML PATH('')), 1, 2, '') AS B_names, C.C_name FROM A LEFT JOIN C ON A.A_no = C.A_no GROUP BY A.A_no, C.C_name
2. 在C#代码中预处理数据源
如果没法修改SQL语句,那可以在绑定GridView之前,先处理DataTable或List,把重复的B列值替换为空:
// 假设你已经从数据库获取到了DataTable dt string lastAno = string.Empty; // 务必确保数据已经按A_no排序,否则同一A_no的记录可能不连续 foreach (DataRow row in dt.Rows) { string currentAno = row["A_no"].ToString(); if (currentAno == lastAno) { // 和上一行A_no相同,清空B列内容 row["B_name"] = string.Empty; } else { // 新的A_no,保留B列值并更新标记 lastAno = currentAno; } } // 绑定到GridView GridView1.DataSource = dt; GridView1.DataBind();
3. 在GridView的RowDataBound事件中处理(显示层控制)
要是不想动数据源,也可以在GridView绑定每行的时候,动态判断并隐藏重复的B列内容:
// 全局变量记录上一行的A_no private string _lastAno = string.Empty; protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { DataRowView drv = e.Row.DataItem as DataRowView; string currentAno = drv["A_no"].ToString(); // 获取B列对应的单元格(假设是第2列,索引从0开始) TableCell bCell = e.Row.Cells[1]; if (currentAno == _lastAno) { // 和上一行A_no相同,清空单元格内容 bCell.Text = string.Empty; // 如果需要合并单元格,可以设置rowspan,不过逻辑会更复杂,需要提前统计同一A_no的行数 } else { // 更新标记为当前A_no _lastAno = currentAno; } } } // 注意:如果GridView开启了分页,需要在PageIndexChanging事件中重置_lastAno protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e) { _lastAno = string.Empty; GridView1.PageIndex = e.NewPageIndex; GridView1.DataBind(); }
这样处理后,GridView里的B列就不会重复显示啦,根据你的实际场景选最合适的方法就行~
内容的提问来源于stack exchange,提问作者sam
相关产品推荐
相关产品推荐

