当前位置: 首页 > news >正文

网站程可以自己做吗c语言 网站开发

网站程可以自己做吗,c语言 网站开发,电子产品开发流程,广西建设官方网站摘要 本文以一个实际可运行的 ASP.NET WebForms 示例(项目名:WebSite6-4,页面:DataReader.aspx)为载体,讲解如何使用 SqlDataReader(即题目中的 DataReader 对象)从数据库读取用户数…

在这里插入图片描述

摘要

本文以一个实际可运行的 ASP.NET WebForms 示例(项目名:WebSite6-4,页面:DataReader.aspx)为载体,讲解如何使用 SqlDataReader(即题目中的 DataReader 对象)从数据库读取用户数据并展示到页面中。文章风格贴近日常交流,侧重实战:包括完整代码、逐段详细解析、示例测试数据与输出、以及复杂度分析和总结。你可以把本文当成把散乱代码整理成可用功能的手册。

描述(场景)

想象你在做一个简单的博客后台或管理系统,数据库里有一张 Users 表,存放网站注册用户的数据。管理员需要一个页面:

  • 初次打开时展示用户列表;
  • 支持按用户名模糊搜索或按角色过滤(例如:管理员、编辑、普通用户);
  • 支持导出当前查询结果为 CSV(便于备份或在 Excel 中查看);
  • 要求读取过程尽量快、占用资源少(表可能有成千上万条记录)。

这正是 SqlDataReader 发挥优势的场景:它是快速、只向前、基于连接的读取器,适合逐行、流式读取大结果集,内存占用低。

下面我们把题目中给的零散代码整理成一个完整、合理、且具备实际功能的页面:

  • 页面名:DataReader.aspx(和 DataReader.aspx.cs 后端);
  • 功能:显示用户表、支持搜索/过滤、导出 CSV;
  • 注意事项:使用参数化查询防注入、使用 using 释放资源、对空值处理与 HTML 编码以防 XSS。

题解答案(完整代码)

下面给出完整的页面和后端代码,拷贝到 WebSite6-4 项目对应文件即可运行(注意替换连接字符串)。

DataReader.aspx(页面标记)

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="DataReader.aspx.cs" Inherits="WebSite6_4_DataReader" %>
<!DOCTYPE html>
<html>
<head><meta charset="utf-8" /><title>用户列表(DataReader 示例)</title>
</head>
<body><form id="form1" runat="server"><div><label>用户名:</label><asp:TextBox ID="txtSearch" runat="server" Width="200"></asp:TextBox><label>角色:</label><asp:DropDownList ID="ddlRole" runat="server"><asp:ListItem Value="">全部</asp:ListItem><asp:ListItem Value="Admin">管理员</asp:ListItem><asp:ListItem Value="Editor">编辑</asp:ListItem><asp:ListItem Value="User">普通用户</asp:ListItem></asp:DropDownList><asp:Button ID="btnSearch" runat="server" Text="查询" OnClick="btnSearch_Click" /><asp:Button ID="btnExport" runat="server" Text="导出 CSV" OnClick="btnExport_Click" /></div><hr /><asp:Literal ID="ltResult" runat="server"></asp:Literal></form>
</body>
</html>

DataReader.aspx.cs(后端 C#)

using System;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Web;
using System.Web.UI;public partial class WebSite6_4_DataReader : System.Web.UI.Page
{// 请根据你的环境修改连接字符串(示例使用 Windows 身份验证连接本机)private static readonly string ConStr = "Server=.;Database=MyBlog;Integrated Security=true;";protected void Page_Load(object sender, EventArgs e){if (!IsPostBack){// 初次加载显示全部用户(或可限制条数以防表过大)LoadUsers(null, null);}}protected void btnSearch_Click(object sender, EventArgs e){string username = txtSearch.Text.Trim();string role = ddlRole.SelectedValue;LoadUsers(username, role);}private void LoadUsers(string usernameFilter, string roleFilter){StringBuilder sb = new StringBuilder();using (SqlConnection conn = new SqlConnection(ConStr))using (SqlCommand cmd = conn.CreateCommand()){// 基本查询,选出常用字段cmd.CommandText = @"SELECT Id, Username, FullName, Email, Role, CreatedAt FROM Users WHERE 1=1";if (!string.IsNullOrEmpty(usernameFilter)){cmd.CommandText += " AND Username LIKE @username";cmd.Parameters.AddWithValue("@username", "%" + usernameFilter + "%");}if (!string.IsNullOrEmpty(roleFilter)){cmd.CommandText += " AND Role = @role";cmd.Parameters.AddWithValue("@role", roleFilter);}cmd.CommandText += " ORDER BY CreatedAt DESC"; // 按注册时间倒序显示,常见需求conn.Open();// 使用 CommandBehavior.CloseConnection 可以在 reader 关闭时自动关闭连接using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)){// 如果没有行,给出友好提示if (!dr.HasRows){ltResult.Text = "<p>没有找到符合条件的用户。</p>";return;}// 构建表格头部(字段名)sb.AppendLine("<table border=1 cellpadding=6 cellspacing=0>");sb.AppendLine("<tr style=\"background:#f0f0f0;\">");for (int i = 0; i < dr.FieldCount; i++){// HtmlEncode 输出,防止存库后有异常字符或 XSSsb.AppendFormat("<th>{0}</th>", HttpUtility.HtmlEncode(dr.GetName(i)));}sb.AppendLine("</tr>");// 逐行读取while (dr.Read()){sb.AppendLine("<tr>");for (int j = 0; j < dr.FieldCount; j++){object val = dr.GetValue(j);// 对空值做处理string text = val == DBNull.Value ? "" : val.ToString();// 对日期做格式化(示例)if (val is DateTime dt){text = dt.ToString("yyyy-MM-dd HH:mm:ss");}sb.AppendFormat("<td>{0}</td>", HttpUtility.HtmlEncode(text));}sb.AppendLine("</tr>");}sb.AppendLine("</table>");ltResult.Text = sb.ToString();}}}// 导出 CSV(使用相同的查询条件)protected void btnExport_Click(object sender, EventArgs e){string username = txtSearch.Text.Trim();string role = ddlRole.SelectedValue;using (SqlConnection conn = new SqlConnection(ConStr))using (SqlCommand cmd = conn.CreateCommand()){cmd.CommandText = @"SELECT Id, Username, FullName, Email, Role, CreatedAt FROM Users WHERE 1=1";if (!string.IsNullOrEmpty(username)){cmd.CommandText += " AND Username LIKE @username";cmd.Parameters.AddWithValue("@username", "%" + username + "%");}if (!string.IsNullOrEmpty(role)){cmd.CommandText += " AND Role = @role";cmd.Parameters.AddWithValue("@role", role);}cmd.CommandText += " ORDER BY CreatedAt DESC";conn.Open();using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)){// 输出 CSV 到响应流Response.Clear();Response.ContentType = "text/csv";Response.ContentEncoding = System.Text.Encoding.UTF8;Response.Charset = "utf-8";Response.AddHeader("Content-Disposition", "attachment;filename=Users.csv");// 写表头for (int i = 0; i < dr.FieldCount; i++){if (i > 0) Response.Write(",");Response.Write('"' + dr.GetName(i).Replace("\"", "\"\"") + '"');}Response.Write("\n");// 写数据行while (dr.Read()){for (int j = 0; j < dr.FieldCount; j++){if (j > 0) Response.Write(",");object val = dr.GetValue(j);string text = val == DBNull.Value ? "" : val.ToString();if (val is DateTime dt){text = dt.ToString("yyyy-MM-dd HH:mm:ss");}// 简单 CSV 转义(把双引号替换为两个双引号)text = text.Replace("\"", "\"\"");Response.Write('"' + text + '"');}Response.Write("\n");}Response.Flush();Response.End();}}}
}

题解代码分析(逐段说明)

下面把关键代码段拆开来解释,顺序对应上面的实现:

连接字符串与基本结构

private static readonly string ConStr = "Server=.;Database=MyBlog;Integrated Security=true;";

说明:这条用于连接本地 SQL Server 的字符串采用 Windows 身份验证(Integrated Security=true)。如果你使用 SQL 登录,请替换为 Server=服务器名;Database=数据库名;User Id=用户名;Password=密码;。把连接信息放到 web.config 中更安全(避免源码硬编码)。

LoadUsers 方法(主读取逻辑)

using (SqlConnection conn = new SqlConnection(ConStr))
using (SqlCommand cmd = conn.CreateCommand())
{cmd.CommandText = "SELECT ... FROM Users WHERE 1=1";// 根据条件追加 SQL,并添加参数conn.Open();using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)){while (dr.Read()) { ... }}
}

要点:

  • using 块保证无论是否抛异常都会正确释放资源(IDisposable);
  • 拼接 SQL 时使用参数 @username@role 并通过 Parameters.AddWithValue 传值,防止 SQL 注入;
  • ExecuteReader(CommandBehavior.CloseConnection):当 dr 关闭后,连接也会自动关闭,这是一个常见且安全的做法;
  • dr.HasRows 可以先判断是否有结果,给出友好提示;
  • dr.FieldCountdr.GetName(i)dr.GetValue(i) 用于动态列处理(不需要硬编码列头);
  • 输出到页面时用 HttpUtility.HtmlEncode(...) 避免用户数据里含有 HTML 或脚本导致的 XSS 漏洞。

处理 DBNull、类型与格式化

object val = dr.GetValue(j);
string text = val == DBNull.Value ? "" : val.ToString();
if (val is DateTime dt) { text = dt.ToString("yyyy-MM-dd HH:mm:ss"); }
sb.AppendFormat("<td>{0}</td>", HttpUtility.HtmlEncode(text));

解释:读取数据库值时要考虑空值(DBNull.Value),另外对于 DateTime 等类型可以做格式化,以便展示更友好的人类可读字符串。

导出 CSV(流式输出)

导出 CSV 的实现沿用了相同的 SQL 查询,但输出到 Response,同时注意以下几点:

  • 设置 Response.ContentType = "text/csv" 并设置 Content-Disposition 以便浏览器弹出下载对话框;
  • 写表头、写数据行、对包含双引号的字段做转义(CSV 中双引号用两个双引号表示);
  • 对于非常大的表,可能需要禁用 Response 缓冲(例如 Response.BufferOutput = false)并周期性 Response.Flush(),以避免内存占用过高;
  • Response.End() 会抛出 ThreadAbortException,如果不喜欢这个行为,可以改用 HttpContext.Current.ApplicationInstance.CompleteRequest()

示例测试及结果

下面给出一个简化的 Users 表结构和测试数据,配合页面可以直接观察输出结果:

CREATE TABLE Users(Id INT IDENTITY(1,1) PRIMARY KEY,Username NVARCHAR(50),FullName NVARCHAR(100),Email NVARCHAR(100),Role NVARCHAR(50),CreatedAt DATETIME
);INSERT INTO Users (Username, FullName, Email, Role, CreatedAt) VALUES
('zhangsan', '张三', 'zhangsan@example.com', 'User', '2024-01-10 09:00:00'),
('lisi', '李四', 'lisi@example.com', 'Editor', '2024-03-02 14:22:10'),
('admin', '系统管理员', 'admin@example.com', 'Admin', '2023-12-30 08:05:05');

在页面上:

  • 初次打开会看到一个三列(Id/Username/FullName/Email/Role/CreatedAt)的表格,按 CreatedAt 倒序;
  • 输入 zhang 做模糊搜索,能返回 zhangsan 的行;
  • 选择角色 Admin 并查询,只会显示 admin
  • 点击导出 CSV,会下载名为 Users.csv 的文件,内容格式类似:
"Id","Username","FullName","Email","Role","CreatedAt"
"3","admin","系统管理员","admin@example.com","Admin","2023-12-30 08:05:05"
...

上面这些行为可以在本地站点运行后直接验证。

时间复杂度

读取 n 行记录时,主要耗时是遍历结果集并把每一行写到 HTML(或 CSV)中,因此时间复杂度为 O(n * m),其中 n 为行数,m 为每行列数(通常认为常量),常简化为 O(n)。也就是说,随着读取行数线性增长,耗时大体上也线性增长。

需要注意:如果查询本身有复杂的 WHERE、JOIN 或未命中索引,那数据库端的查询成本会更高 —— 这不是 DataReader 的问题,是 SQL 查询与索引策略的问题。

空间复杂度

使用 SqlDataReader 的优点之一是低内存占用:它是基于连接的流式读取器,数据库返回多少,代码就读取多少,通常只在内存中保留当前一行的数据。因此空间复杂度大致为 O(1)(忽略用于输出 HTML 的缓冲 StringBuilder,如果你把整个结果放进 StringBuilder,内存会随行数增加;为减少内存,建议直接把行写入响应流或分页读取)。

如果输出较大,建议采用分页查询(TOP / OFFSET-FETCHROW_NUMBER())或直接把读取结果逐行 Response.Write 并周期 Response.Flush() 来避免占用过多内存。

总结

  • SqlDataReader 非常适合需要快速、逐行读取大量数据的场景(例如导出、生成流式响应、展示长列表);
  • 使用 using、参数化查询和 HttpUtility.HtmlEncode 是三条重要的实践:保证资源释放、防止注入与防止 XSS;
  • 对于需要回溯、修改或绑定到 UI 的场景,可以考虑 DataTable/DataSet(断开连接)或 ORM(比如 EF);如果只是只读展示或导出,DataReader 更省内存且更快;
  • 大数据量时,尽量在 SQL 端做筛选与分页,避免将完整表一次性读到内存;
  • 导出文件时注意字符编码(如 UTF-8 BOM 的需求)和 CSV 转义规则。
http://www.dtcms.com/a/568035.html

相关文章:

  • 太仓建设银行网站微信小程序加盟
  • 站酷海报设计图片深圳医疗网站建设
  • 网站建设需要多少技术各省住房和城乡建设厅网站
  • jquery 网站模板如何制作网页图
  • 建论坛网站seo搜索引擎优化课后答案
  • 网站建设行业知乎免费课程网站有哪些
  • 360怎么变成建设银行首选网站网站建设的空间是什么
  • 网站一次性链接怎么做怎么做高端品牌网站设计
  • 网站后台管理规定美食网站开发与设计文献综述
  • 陕西网站建设哪家专业广西住房和建设厅官网
  • 投资做网站网络服务器的配置与应用心得
  • 重庆有哪些科技骗子公司wordpress4.7优化
  • 如何高效建设品牌网站如何下载wordpress
  • 卡片形式的网站wordpress 批量标签
  • wordpress纯代码下载seo搜索引擎优化薪资
  • 销售网站开发步骤网站以什么名字备案
  • 大宗贸易采购平台福州网站怎么做seo
  • 淘宝的网站怎么做内容营销策略
  • 成都网站定制wordpress ip_hash失效
  • 门户网站还能建设么cida室内设计师资格证
  • 企业网站建设具体步骤网站建设中 怎么办
  • 承接网站建设服务一个公司可以做几个网站吗
  • windows 网站模板热点新闻素材
  • 积分兑换商城网站建设随州企业网络推广怎么做
  • 建设营销网站多少钱wordpress启用主题404
  • 玩具 东莞网站建设 技术支持建设现金分期网站
  • 网站推广打包爱网站关键词挖掘工具
  • 做网站费是多少政务网站设计鉴赏
  • 单位网站备案交友免费网站建设
  • 建设网站的费用怎么做账最打动人心的广告语