使用Repeater控件展示数据库数据时,如何实现总价求和?
解决Repeater展示数据时的总价求和问题
首先看你代码里的几个关键问题:
- 你声明了
DataTable dataTable但没有填充数据,直接用ccmd.ExecuteReader()绑定Repeater后,dataTable还是空的,所以后续的dataTable.Select("SUM(Price)")肯定拿不到结果 - 直接拼接SQL语句存在SQL注入风险,这是很危险的操作,必须改成参数化查询
DataTable.Select()方法是用来筛选行的,不是用来做聚合计算的,不能直接用它求和
下面给你三种可行的解决方案,你可以根据需求选择:
方案1:在SQL查询中直接计算总价(推荐,性能最优)
让数据库直接帮你计算总和,这是最高效的方式,同时修复SQL注入问题:
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString)) { con.Open(); // 同时查询明细和总价,用参数化避免注入 string cquery = @"SELECT cart.ProductID, ProName, Size, Colour, Price, (SELECT SUM(p.Price) FROM cart c JOIN Products p ON c.ProductID = p.ProductID WHERE c.Custid = @Custid) AS TotalPrice FROM cart JOIN Products ON Products.ProductID = cart.ProductID WHERE Custid = @Custid"; SqlCommand ccmd = new SqlCommand(cquery, con); // 添加参数,替换字符串拼接 ccmd.Parameters.AddWithValue("@Custid", Session["custid"]); DataTable dataTable = new DataTable(); // 用SqlDataAdapter填充DataTable new SqlDataAdapter(ccmd).Fill(dataTable); // 绑定Repeater CRepeater.DataSource = dataTable; CRepeater.DataBind(); // 获取总价(只要取第一行的TotalPrice即可,因为所有行的TotalPrice都一样) if (dataTable.Rows.Count > 0) { Label3.Text = dataTable.Rows[0]["TotalPrice"].ToString(); } }
方案2:填充DataTable后在代码中计算总和
如果不想修改SQL,可以先把数据填充到DataTable,再通过Linq或者循环计算总和:
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString)) { con.Open(); string cquery = @"SELECT cart.ProductID, ProName, Size, Colour, Price FROM cart JOIN Products ON Products.ProductID = cart.ProductID WHERE Custid = @Custid"; SqlCommand ccmd = new SqlCommand(cquery, con); ccmd.Parameters.AddWithValue("@Custid", Session["custid"]); DataTable dataTable = new DataTable(); new SqlDataAdapter(ccmd).Fill(dataTable); CRepeater.DataSource = dataTable; CRepeater.DataBind(); // 计算总价:用Linq求和 decimal totalPrice = dataTable.AsEnumerable() .Sum(row => row.Field<decimal>("Price")); Label3.Text = totalPrice.ToString(); }
方案3:在Repeater的ItemDataBound事件中累加
这种方式适合需要在绑定每一行数据时实时累加的场景,比如想在页面上动态显示当前总价:
首先在后台声明一个全局的累加变量:
private decimal _totalPrice = 0;
然后绑定Repeater的ItemDataBound事件:
protected void CRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e) { if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { // 获取当前行的Price值 DataRowView row = (DataRowView)e.Item.DataItem; decimal price = Convert.ToDecimal(row["Price"]); _totalPrice += price; } // 绑定完成后给Label赋值 if (e.Item.ItemType == ListItemType.Footer) { Label3.Text = _totalPrice.ToString(); } }
注意要在Repeater的aspx代码中添加OnItemDataBound="CRepeater_ItemDataBound"属性,同时别忘了用参数化查询填充数据绑定Repeater。
另外,一定要养成用using语句包裹数据库连接的习惯,它会自动帮你释放资源,避免连接泄漏。
内容的提问来源于stack exchange,提问作者dadigun
相关产品推荐
相关产品推荐

