切换导航
{{systemName}}
{{ info.Title }}
{{info.Title}}
{{ menu.Title }}
{{menu.Title}}
登录
|
退出
搜索
秘籍列表
ASP.NET基础及企业项目应用
必备工具的安装及C#基础的介绍
ASP.NET高级
数据库操作
Web前端基础
ASP.NET建站核心
ASP.NET MVC
.Net项目
ASP.NET 数据库及各种ORM使用教程
面试
ASP.NET建站核心
[TOC] 如果你耐心的我学了上面前四章的基础内容你会发现你还不知道如何设计出一个动态网站,但是如果你学习了本章内容,你就了解了如何去创建一个动态网站,学完这章你大可实践一把。 [【第五章ASP.NET建站核心(ASP.NET编程教学)视频】](https://www.bilibili.com/video/BV1gW411o7cS/?share_source=copy_web&vd_source=160a6bb7aac774f8784a54ccad1255a1 "【第五章ASP.NET建站核心(ASP.NET编程教学)视频】") ####第一节网站的部署及动静态网站介绍 #####1.动静态网站区别 (1)动态与静态从字眼可以很明白的说明,动态网站就是指网上的浏览者可以与你的网站进行互动,交流,这样就有了互动性。静态网站指浏览者呢只能看,没有互动性,就像是广告一样,哪么什么注册了留言了都是做不了的。 (2)静态网站的每个页面是存在于服务器上的,访问过程相当于直接访问文件,有利于用户的检索;动态网站大部分数据都是会实时更新的的,而服务器上存的只是该页面的一部分,动态网站通常也会使用页面静态化技术来优化自己的网站。 (3)静态网页没有数据库的支持,在网站制作和维护方面工作量较大,因此当网站信息量很大时完全依靠静态页面是比较困难的。 (4)静态网页的交互性在功能方面有较大的限制,你看到的图片什么的是动的并不代表他是动态网站。一般动态网站是通过数据库进行数据维护的。动态网站除了有网页设计外,往往还有数据库设计及程序进行控制自动的和高级的功能。 (5)动态网站体现在网页一般是以asp,jsp,php,aspx等结束。服务器空间配置要比静态的网页要求高,费用也相应的高,不过动态网页利于网站内容的更新,适合企业建站,如:www.jiyuwu.com。而静态网站是指全部由HTML代码格式页面组成的网站,网站主要是静态化的页面和代码组成,一般文件名均以htm、html、shtml等为后缀,如:https://templet.jiyuwu.com/store/2022/3/F073F4C767F046D4AA87472FE4F3AA6D/index.html #####2.用配置IIS并发布网站 (1)安装IIS服务器:控制面板->卸载程序->启用或关闭window功能->Internet Information Services/Internet Information Services 可承载的Web核心选中->确定->更改完成关闭。  (2)发布一个静态网站:控制面板->选择小图标->管理工具-> Internet Information Services双击->新建一个网站项鼠标右键或鼠标右键Default Web Site->浏览->粘贴你的项目->点击浏览网站查看。   (3)403.14处理:一般不建议启用目录,建议添加一下你的默认页。  ####第二节Http协议与请求响应过程详解 #####1.Http协议的简介 协议:约束双方的规范准则。 超文本传输协议(HTTP,HyperText Transfer Protocol),从名字上很容易理解,Http协议就是将超文本标记语言的文档(即Html文档),设计Http最初目的为了提供一种发布和接收Html页面的方法,用来约束请求与响应。它属于一个应用层的协议。 #####2.Web访问的工作过程 (1)将域名(网址)转换为IP地址 当用户要访问网络中的某个网页时,如www.baidu.com,首先回到电脑本地的Hosts文件查找IP,找不到就向DNS(域名服务器)发出请求,告诉DNS说:"我要把www.baidu.com转化为它所定义的IP地址",这里可以简单把DNS理解为一个字典,知道域名就可以知道域名对应的IP地址,他们有这个一个映射的关系。DNS收到请求后查询,查到对应的IP地址为115.239.210.27。 (2)根据IP和端口访问主机网站 浏览器(客户端)向IP地址为115.239.210.27的主机发出与端口号80建一条TCP连接请求(HTTP协议是建立在传输层TCP的基础上的),80端口是服务器提供web服务的默认端口。建立连接后,浏览器发出一条HTTP请求,如 GET http://www.baidu.com/ HTTP/1.1。当域名为www.baidu.com的服务器接受到请求后,向浏览器发送一个html文件文件发送完后,由服务器主动关闭TCP连接。浏览器接收传送来的页面并显示。 (3)静态文件或图片的获取 如果Html文件中包含图片或要下载的文件,还要与服务器再次建立一个TCP连接,以便可以下载图片或文件,下载文件即完成超文本文件的传送,HTTP协议是web服务器的基础,由于文件及图片的获取是一次新的请求,所以网站可以将静态的资源与网站分离到不同服务器以减轻服务器压力,当然几百人访问的小项目不用考虑那么多,如果访问量足够大,这些都是必做的。 #####3.Http组成 (1)请求。 (2)响应。 结论:请求与响应是成对存在的。 #####4.Http请求的发送方式 (1)通过浏览器的地址栏 (2)通过html当中的Form表单提交 (3)通过a链接的href (4)通过ajax提交(安全性考虑,不能对文件进行操作) (5)src属性 #####5.Http请求 https://www.baidu.com/?Username=Baidu&PWD=123进行F12查看 (1)请求行 (1 请求方式:get,post,delete,put等。 (2 请求的资源:https://www.baidu.com/?Username=Baidu&PWD=123 (3 协议版本:Http/1.0,发生请求,创建一次连接,获取一个web资源并断开连接。Http/1.1, 发生请求,创建一次连接,获取一个web资源并保持连接。 (2)请求头 客户端的一些信息,用户不需要对其进行设置,使用键值对表示(key:value)。 (3)请求体 请求为post时,请求体会有请求参数;请求为get时,参数不会出现在请求体中,会出现在url后面。 (4)示意图  #####6.Http响应 (1)响应行 (1 状态码:200,请求成功。302,重定向。304,请求资源没有改变,访问本地缓存。404,资源不存在。500,服务器内部错误。等等。 (2 协议版本。 (2)响应头 服务器信息以键值对形式返回给客户端,也是自动返回的内容。 (3)响应体 服务器返回给客户端的页面正文,浏览器加载到内存,解析渲染显示。 (4)示意图  #####7.Http请求方式 (1)8种请求类型 序号|方法|描述 -|-|- 1|GET|请求指定的页面信息,并返回实体主体。 2|HEAD|类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头 3|POST|向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 4|PUT|从客户端向服务器传送的数据取代指定的文档的内容。 5|DELETE|请求服务器删除指定的页面。 6|CONNECT|HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。 7|OPTIONS|允许客户端查看服务器的性能。 8|TRACE|回显服务器收到的请求,主要用于测试或诊断 (2)常用请求post和get的区别 (1 GET在浏览器回退时是无害的,而POST会再次提交请求。 (2 GET产生的URL地址可以被Bookmark,而POST不可以。 (3 GET请求会被浏览器主动cache,而POST不会,除非手动设置。 (4 GET请求只能进行url编码,而POST支持多种编码方式。 (5 GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。 (6 GET请求在URL中传送的参数是有长度限制的,而POST没有。 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。 (7 GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。 (8 GET参数通过URL传递,POST放在Request body中。 注意:面试常问,怎么也要回答四个吧! ####第三节Ajax及一般处理程序 #####1. Ajax及一般处理程序简介 (1)Ajax(Asynchronous JavaScript And XML)介绍 通过在幕后与 web 服务器交换数据,而不是每当用户作出改变时重载整个 web 页面,AJAX 技术可以使网页更迅速地响应。AJAX是一种进行页面局部异步刷新的技术。开发一个AJAX功能需要开发服务端和客户端两块程序。 没有AJAX会怎么样?普通的ASP.Net每次执行服务端方法的时候都要刷新当前页面。在youku看视频的过程中如果提交评论,页面就不会刷新,视频不会被打断就需要Ajax了。 (2)一般处理程序介绍 ashx 文件用于写web handler的。.ashx文件与.aspx文件类似,可以通过它来调用HttpHandler类,它免去了普通.aspx页面的控件解析以及页面处理的过程。所以没有那么多事件需要处理,不必消耗太多资源,所以性能方面要比aspx高。 .ashx文件适合产生供浏览器处理的、不需要回发处理的数据格式,例如用于生成动态图片、动态文本等内容。 #####2. 手写一个Ajax (1)编写ajax ``` function ajax(url, onsuccess, onfail) { var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");//选择创建的对象类型 xhr.open("POST", url, true); //选择请求方式,地址及不等待有结果继续 xhr.onreadystatechange = function () {//readyState改变触发 if (xhr.readyState == 4) {//请求已完成,响应已就绪 if (xhr.status == 200) {//ok onsuccess(xhr.responseText); } else { if (onfail) { onfail(xhr.status); } } } }; xhr.send();//发送http请求 } ``` (2)编写html ``` <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script src="js/jiyuwu_ajax.js"></script> <script> window.onload = function () { ajax("LoadUser.ashx", function (resTxt) { var users = resTxt.split("|"); for (var i = 0; i < users.length; i++) { var user = users[i]; var fields = user.split(","); var id = fields[0]; var username = fields[1]; var password = fields[2]; $("#tbody1").append($("<tr><td>" + id + "</td><td>" + username + "</td><td>" + password + "</td></tr>")); } }, function (status) { alert("加载错误"); }); } </script> </head> <body> <table> <thead> <tr><th>id</th><th>用户名</th><th>密码</th></tr> </thead> <tbody id="tbody1"></tbody> </table> </body> </html> ``` (3)编写一般处理程序 ``` context.Response.ContentType = "text/plain"; List<string> list = new List<string>(); list.Add("1,柯南,kenan"); list.Add("2,机遇屋,jiyuwu"); string str = string.Join("|", list); context.Response.Write(str); 3. Jquery中的Ajax使用 (1)使用ajax请求后台数据 <script src="js/jquery-1.8.3.min.js"></script> <script type="text/javascript"> $(function () { $.ajax({ type: "post", url:"JqueryAjax.ashx", data: { method: "getData", userName: "jiyuwu" }, success: function (nums) { //如果服务器返回的报文contenttype为:application/json,那么jquery也会自动把报文体转换为JavaScript对象,传递给success指向的匿名方法 for (var i = 0; i < nums.length; i++) { alert(nums[i]); } }, error: function () { alert("ajax出错"); } }); }); </script> ``` (3)使用ashx数据返回 ``` public void ProcessRequest(HttpContext context) { context.Response.ContentType = "application/json"; if (context.Request["method"] == "getData" && context.Request["userName"] == "jiyuwu") { int[] nums = new int[] { 3, 5, 89 }; JavaScriptSerializer jss = new JavaScriptSerializer(); string json = jss.Serialize(nums); context.Response.Write(json); } else { context.Response.Write("error"); } } ``` ####第四节cookie和session #####1. Cookie介绍及使用说明 Cookie是和站点相关的,是保存在浏览器端的,并且每次向服务器请求的时候除了发送表单参数外,还会将和站点相关的所有Cookie都提交给服务器,将服务端返回的Cookie更新回浏览器,因此可以将信息保存在Cookie中,然后在服务器端读取、修改。 在删除Cookie时,Request.Cookies.Clear()这个方法并不是删除Cookie。由于 Cookie 在用户的计算机中,因此无法将其直接移除,我们可以设置一个同名过期的Cookie,当浏览器发现过期了,浏览器就会帮我们进行丢弃。 案例:记住用户名 (1)设置值: ``` HttpContext.Current.Response.AppendCookie(new HttpCookie("UserName", "JIYUWU") { Expires = System.DateTime.Now.AddHours(2) }); ``` (2)读取值(这里记录日志用的JIYUWU.TXT可在nuget安装): ``` try { string username = HttpContext.Current.Request.Cookies["UserName"].Value; this.Label1.Text = username; } catch (Exception ex) { string path = MapPath(""); JIYUWU.TXT.TXTHelper.WriteLog(ex.ToString(), path); this.Label1.Text = "没有值呢!"; } ``` (3)清除值: ``` HttpContext.Current.Response.AppendCookie(new HttpCookie("UserName", "JIYUWU") { Expires = System.DateTime.Now.AddHours(-1) }); ``` 如果不设定Expires那么生命周期则是关闭浏览器则终止,否则“最多”到Expires的时候终止。 (4)Cookie的缺点: 还不能存储过多信息,机密信息不能存(不要把不希望用户看到的或者不能被用户篡改的信息放到Cookie)。 是可以被清除,不能把不能丢的数据存到Cookie中,也许没到Expires就已经过期了。 Cookie无法跨不同的浏览器。 无法跨域名读写,www.jiyuwu.com无法读写www.jiyuwu.com的Cookie。 子域名的问题:www.jiyuwu.com设置的Cookie默认无法被api.jiyuwu.com 读写,如果要想能够操作,则需要写入Cookie的时候设置Domain为“.jiyuwu.com”。 #####2. Session的介绍及使用说明 (1)内置Session 核心信息放到服务器上,客户端无法去篡改。Cookie不能存储机密数据。要使用ASP.Net已经内置的Session机制。普通的HttpHandler要能够操作Session,要实现IRequiresSessionState接口,这个接口是没有任何方法的“标记接口”,因为session处理会稍微降低系统性能,所以 HttpHandler 默认不处理Session,asp.net引擎如果看到ashx实现了IRequiresSessionState,则帮咱们处理。 Cookie是存在客户端,Session是存在服务器端,目的是一样的:保存和当前客户端相关的数据(当前网站的任何一个页面都能取到Session)。 Session有自动销毁机制,如果一段时间内浏览器没有和服务器发生任何的交互,则Session会定时销毁。这也就是为什么一段时间不操作,系统就会自动退出。 在web.config的system.web节点下配置sessionState节点的timeout,单位是分钟,默认是20(也只是一个建议,也许服务器10分钟的时候就让Session失效了)。 <sessionState mode="InProc" cookieless="false" timeout="20"></sessionState> Session和Cookie的关系:通过查看Http报文发现,Cookie中放了一个SessionId,服务器中保存SessionId和数据的对应关系。 自己实现: Guid 算法简介:根据网卡mac地址、系统时间、CPU时钟周期等算出来的值,这个值在同一台电脑上多次调用不会产生重复的值,在不同电脑的同一时刻调用也不会重复,可以保证“全球唯一”。Guid.NewGuid();不要用new Guid(),否则产生的是空的。 在服务器中生成Guid(SessionId)到Cookie中,然后在服务器中建立一个以Guid为文件名的文件,文件内容为session的值。 (2)进程外的Session Session默认是保存在Web服务器内存中的(InProc),当Web服务器重启之后Session就丢失了,造成用户反复登录的问题。重启服务器再看刷新读Session的页面验证一下。  (1 Session保存在SQLServer中,配置方法见备注。重启服务器再看刷新读Session的页面验证一下。 首先cd C:\Windows\Microsoft.NET\Framework\v4.0.30319 然后执行 aspnet_regsql.exe -S 服务器名 -U 用户名 -P 密码 -ssadd -sstype c -d 数据库名 即:你要将Session保存到哪个数据库下。点击回车键后,直到执行完毕。以上运行完毕后,我们打开SqlServer ,找到sales数据库。我们发现下面给我们自动生成了两个表,之后配置webconfig ``` <sessionState mode="SQLServer" sqlConnectionString="data source=127.0.0.1;user id=sa;password=1" cookieless="false" timeout="20"></sessionState> ``` (2 Session还可以保存在StateServer中, StateServer是Windows的一个服务,具体配置方法自行百度,培养自学能力。 ``` <sessionState mode="StateServer" stateConnectionString="tcpip=tcpip=127.0.0.1:42424" cookieless="false" timeout="20"></sessionState> ``` 进程外Session的对象需要“可序列化”,int、string等这些都可以,除非加标注,否则自定义类不行。以后详细讲“类的序列化” 。 没有绝对的好与坏,根据项目的特点选择合适的技术。 (*)还允许自定义SessionStateProvider。进程外Session也有利于集群。 ####第五节三层架构 三层架构是从整个业务应用角度对程序的划分,其分层逻辑来源于“高内聚(块内联系),低耦合(块外联系)”的思想。三层架构分为:表现层(UI(User Interface))、业务逻辑层(BLL(Business Logic Layer))、数据访问层(DAL(Data Access Layer))再加上实体类库(Model)。考虑一个项目是不是应该应用三层/多层设计时,先得考虑下是不是真的需要? 实际上大部分程序就开个WebApplication就足够了,完全没必要作的这么复杂. 而多层结构,是用于解决真正复杂的项目需求的。 #####1. 表现层(UI) 主要对用户的请求接受,以及数据的返回,为客户端提供应用程序的访问。位于最外层(最上层),最接近用户。用于显示数据和接收用户输入的数据,为用户提供一种交互式操作的界面。 #####2. 业务逻辑层(BLL) 主要负责对数据层的操作。也就是说把一些数据层的操作进行组合。业务逻辑层在体系架构中的位置很关键,它处于数据访问层与表示层中间,起到了数据交换中承上启下的作用。由于层是一种弱耦合结构,层与层之间的依赖是向下的,底层对于上层而言是“无知”的,改变上层的设计对于其调用的底层而言没有任何影响。 #####3. 数据访问层(DAL) 有时候也称为是持久层,其功能主要是负责数据库的访问,可以访问数据库系统、二进制文件、文本文档或是XML文档。 简单的说法就是实现对数据表的Select,Insert,Update,Delete的操作。如果要加入ORM的元素,那么就会包括对象和数据表之间的mapping,以及对象实体的持久化。 #####4. 实体类库(Model) 主要存放数据库中的表字段,可以理解为三层任意一层都可使用的一个类库。 #####5. 优点 (1)开发人员可以只关注整个结构中的其中某一层; (2)可以很容易的用新的实现来替换原有层次的实现; (3)可以降低层与层之间的依赖; (4)有利于标准化; (5)利于各层逻辑的复用。 (6)结构更加的明确 (7)在后期维护的时候,极大地降低了维护成本和维护时间 #####6. 缺点 (1)降低了系统的性能。这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成。 (2)有时会导致级联的修改。这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码。 (3)增加了开发成本。 ####第六节ADO.NET制作自己的SqlHelper 编写SqlHelper类,方便我们执行数据库语句,这时可以直接调用封装在SqlHelper类的方法。现在大多数公司面试的时候,给你的面试题一般会要你自己手写一个SqlHelper的类,这考的是自己的基本功,为帮助大家记忆我画了模型如下图:  ADO.net中常用的对象有哪些: DataSet对象:表示内存中数据的缓存,可以把它想像成一个临时的数据库,它里可以存多个表(DataTable),而且是断开式的,不用每进行一次操作就对数据库进行更新,从而提高了工作效率。 DataReader对象:它与DataSet最大的不同是有连接式的,每次对数据库进行存取都会影响到数据库。 Connection对象:用于连接数据库的对象,表示到数据源的一个唯一的连接。 Command对象:表示要对数据库执行的一个SQL语句或一个存储过程。 DataAdapter对象:该对象是与DataSet配合使用的对象,用于把表填充到DataSet,和更新DataSet等。 编写一个完整的SqlHelper(包含增删改查,事务,存储过程查询并且有详细的注释): 首先在WebConfig添加配置: ``` <connectionStrings> <add name="AppCenterDSN" connectionString="Data Source=DESKTOP-T10BBR1;Initial Catalog=StudentsManagement;Persist Security Info=True;User ID=matt;Password=123456"/> </connectionStrings> 之后编写SqlHelper: public static readonly string connString = ConfigurationManager.ConnectionStrings["AppCenterDSN"].ConnectionString; #region 事务 private static SqlConnection connTr; private static SqlCommand cmdTr; private static SqlTransaction sqlTr; /// <summary> /// 事务开始 /// </summary> public static void BeginTransaction() { connTr = new SqlConnection(connString); connTr.Open(); sqlTr = connTr.BeginTransaction(); } /// <summary> /// 事务方法 /// </summary> /// <param name="sql">数据库语句</param> /// <param name="ps">参数</param> /// <returns></returns> public static int ExecuteTranNonQuery(string sql, params SqlParameter[] ps) { cmdTr = new SqlCommand(sql, connTr); if (connTr.State == ConnectionState.Closed) { connTr.Open();//打开数据库 } if (ps != null) { cmdTr.Parameters.AddRange(ps); } cmdTr.Transaction = sqlTr;//事物 return cmdTr.ExecuteNonQuery(); } /// <summary> /// 提交事务 /// </summary> public static void Commit() { sqlTr.Commit(); } /// <summary> /// 事务回滚 /// </summary> public static void Rollback() { sqlTr.Rollback(); } /// <summary> /// 事务关闭连接 /// </summary> public static void DisTranConnect() { sqlTr.Dispose(); cmdTr.Dispose(); connTr.Close(); connTr.Dispose(); } #endregion #region 执行 增 删 改 /// <summary> /// 执行 增 删 改 /// </summary> /// <param name="Sql">要执行的Sql</param> /// <param name="param">参数</param> /// <returns>影响行数</returns> public static int ExecuteNonQuery(string sql, params SqlParameter[] param) { //实例化连接对象,并指定连接字符串,自动释放资源,不用关闭 using (SqlConnection conn = new SqlConnection(connString)) { //实例化命令对象,指定Sql,与连接对象 using (SqlCommand cmd = new SqlCommand(sql, conn)) { //如果有参数 if (param != null) { //批量添加参数 cmd.Parameters.AddRange(param); } //打开连接 conn.Open(); //执行Sql并返回影响行数 return cmd.ExecuteNonQuery(); } } } #endregion #region 执行 查询 /// <summary> /// 执行 查询 /// </summary> /// <param name="Sql">要执行的Sql</param> /// <param name="param">参数</param> /// <returns>数据集</returns> public static SqlDataReader ExecuteReader(string Sql, params SqlParameter[] param) { //实例化连接对象,并指定连接字符串 SqlConnection conn = new SqlConnection(connString); //实例化命令对象,指定Sql,与连接对象 using (SqlCommand cmd = new SqlCommand(Sql, conn)) { //如果有参数 if (param != null) { //批量添加参数 cmd.Parameters.AddRange(param); } //打开连接 conn.Open(); //执行Sql并返回影响行数,如果将返回的SqlDataReader关闭时也将关闭连接 return cmd.ExecuteReader(CommandBehavior.CloseConnection); } } /// <summary> /// 执行查询存储过程,并且返回一个SqlDataReader对象(使用SqlDataReader对象执行) /// </summary> /// <param name="sql">存储过程名</param> /// <param name="ps">存储过程中需要的参数</param> /// <returns>读取器对象</returns> public static SqlDataReader ExecuteReaderProc(string Sql, params SqlParameter[] param) { //实例化连接对象,并指定连接字符串 SqlConnection conn = new SqlConnection(connString); //实例化命令对象,指定Sql,与连接对象 using (SqlCommand cmd = new SqlCommand(Sql, conn)) { //如果有参数 if (param != null) { //批量添加参数 cmd.Parameters.AddRange(param); } //打开连接 conn.Open(); cmd.CommandType = CommandType.StoredProcedure; //执行Sql并返回影响行数,如果将返回的SqlDataReader关闭时也将关闭连接 return cmd.ExecuteReader(CommandBehavior.CloseConnection); } } #endregion #region 完成数据的查询,返回DataTable /// <summary> /// 完成数据的查询,返回DataTable /// </summary> /// <param name="Sql">要执行的Sql</param> /// <param name="param">参数</param> /// <returns>DataTable</returns> public static DataTable GetTable(string sql, params SqlParameter[] param) { DataTable dt = new DataTable(); //实例化连接对象,并指定连接字符串,自动释放资源,不用关闭 using (SqlConnection conn = new SqlConnection(connString)) using (SqlDataAdapter adp = new SqlDataAdapter(sql, conn)) { if (param != null) { adp.SelectCommand.Parameters.AddRange(param); } adp.Fill(dt); } return dt; } #endregion #region 返回首行首列 /// <summary> /// 返回首行首列 /// </summary> /// <param name="SqlSql">要执行的SqlSql</param> /// <param name="param">参数</param> /// <returns></returns> public static object ExecuteScaler(string Sql, params SqlParameter[] param) { //实例化连接对象,并指定连接字符串 using (SqlConnection conn = new SqlConnection(connString)) //实例化命令对象,指定Sql,与连接对象 using (SqlCommand cmd = new SqlCommand(Sql, conn)) { //如果有参数 if (param != null) { //批量添加参数 cmd.Parameters.AddRange(param); } //打开连接 conn.Open(); //执行Sql return cmd.ExecuteScalar(); } } #endregion ``` 注意:大家看到我们执行语句要进行参数化,进行参数化就是为了防止SQL注入漏洞。 ####第七节实现一个增删改查 这一节就是对前面学的知识的一个实践,我们来做一个简单的小项目,为大家巩固前面知识,可能后期时间多了,我会将这个小项目做的更好并成为开源产品。如果你亲手做过了那么后面面试你也可以直接用到面试中,因为面试可能会让你写一个增删改查程序,好了不多说了让开始吧! 目录结构及数据库设计如下图:  StudentsManagement数据库设计:  #####1.首先配置数据库和公用方法 (1)添加数据库文件SqlHelper.cs并在Web.config配置节点。 (2)CommonHelper.cs解析文本返回内容的操作封装 ``` public class CommonHelper { /// <summary> /// 读取虚拟目录下的文件路径 /// </summary> /// <param name="virtualPath"></param> /// <returns>返回文本内容</returns> public static string ReadHtml(string virtualPath) { string fullPath = HttpContext.Current.Server.MapPath(virtualPath); string html = File.ReadAllText(fullPath); return html; } /// <summary> /// 输出错误信息 /// </summary> /// <param name="mes"></param> public static void OutputError(string mes) { string html = ReadHtml("./Error.html"); html = html.Replace("*message", mes); HttpContext.Current.Response.Write(html); } } ``` #####2.配置管理文件夹(Management) 知识点讲解:首先拿到渲染的页面,通过公用类将页面内容获取为字符串,查询数据库获取数据并拼接为我们想展示效果,最后对标记的字符串进行替换并输出为html页面。 (1)学生管理: (1 StudentManagement.html ``` <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>学生管理</title> </head> <body> <a href="./ClassManagement.ashx"><input type="button" value="管理班级" /></a> <a href="./TeacherManagement.ashx"><input type="button" value="管理教师" /></a><br /> <a href="../ManagementChange/StudentEditAddNew.ashx?action=addNew">新增</a> <table> <thead><tr><th>姓名</th><th>性别</th> <th>生日</th><th>身高</th><th>所属班级</th><th>班主任</th><th>是否特长生</th><th>删除</th><th>编辑</th></tr></thead> *table </table> </body> </html> ``` (2 StudentManagement.ashx ``` public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/html"; string html = CommonHelper.ReadHtml("./StudentManagement.html"); DataTable dt = SqlHelper.GetTable("select s.Id,s.Sname name,s.Ssex sex,s.Sbirthday birthday,s.Sheight height,s.Sability ability,s.Sclass class,c.Cteacher from student s left join class c on s.Sclass=c.Cname"); StringBuilder sb = new StringBuilder(); foreach (DataRow row in dt.Rows) { string getBirthday = Convert.ToString(row["birthday"]); int getNum = getBirthday.IndexOf(" "); getBirthday = getBirthday.Substring(0, getNum); string gender = Convert.ToString(row["sex"]); sb.Append("<tr>").Append("<td>").Append(row["name"]).Append("</td>") .Append("<td>").Append(gender == "True" ? "男" : "女").Append("</td>") .Append("<td>").Append(getBirthday).Append("</td>") .Append("<td>").Append(row["height"]).Append("</td>") .Append("<td>").Append(row["class"]).Append("</td>") .Append("<td>").Append(row["Cteacher"]).Append("</td>") .Append("<td>").Append(row["ability"]).Append("</td>") .Append("<td><a href='../ManagementChange/Delete.ashx?id=").Append(row["Id"]).Append("&method=Student'>删除</td>") .Append("<td><a href='../ManagementChange/StudentEditAddNew.ashx?action=edit&id=").Append(row["Id"]).Append("'>编辑</td>") .Append("</tr>"); } html = html.Replace("*table", sb.ToString()); context.Response.Write(html); } ``` (2)班级管理: ``` (1 ClassManagement.html <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>班级管理</title> </head> <body> <a href="./StudentManagement.ashx"><input type="button" value="管理学生" /></a> <a href="./TeacherManagement.ashx"><input type="button" value="管理教师" /></a><br /> <a href="../ManagementChange/ClassEditAddNew.ashx?action=addNew">新增</a> <table> <thead><tr><th>班级名称</th><th>班号</th> <th>班主任</th><th>删除</th><th>编辑</th></tr></thead> *table </table> </body> </html> ``` (2 ClassManagement.ashx ``` public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/html"; string html = CommonHelper.ReadHtml("./ClassManagement.html"); DataTable dt = SqlHelper.GetTable("select * from class"); StringBuilder sb = new StringBuilder(); foreach (DataRow row in dt.Rows) { sb.Append("<tr>").Append("<td>").Append(row["Cname"]).Append("</td>") .Append("<td>").Append(row["Cnumber"]).Append("</td>") .Append("<td>").Append(row["Cteacher"]).Append("</td>") .Append("<td><a href='../ManagementChange/Delete.ashx?id=").Append(row["Id"]).Append("&method=Class'>删除</td>") .Append("<td><a href='../ManagementChange/ClassEditAddNew.ashx?action=edit&id=").Append(row["Id"]).Append("'>编辑</td>") .Append("</tr>"); } html = html.Replace("*table", sb.ToString()); context.Response.Write(html); } ``` (3)教师管理: (1 TeacherManagement.html ``` <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>教师管理</title> </head> <body> <a href="./ClassManagement.ashx"><input type="button" value="管理班级" /></a> <a href="./StudentManagement.ashx"><input type="button" value="管理学生" /></a><br /> <a href="../ManagementChange/TeacherEditAddNew.ashx?action=addNew">新增</a> <table> <thead><tr><th>姓名</th><th>生日</th><th>电话</th><th>邮箱</th><th>删除</th><th>编辑</th></tr></thead> *table </table> </body> </html> ``` (2 TeacherManagement.ashx ``` public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/html"; string html = CommonHelper.ReadHtml("./TeacherManagement.html"); DataTable dt = SqlHelper.GetTable("select * from teacher"); StringBuilder sb = new StringBuilder(); foreach (DataRow row in dt.Rows) { string getBirthday = Convert.ToString(row["Tbirthday"]); int getNum = getBirthday.IndexOf(" "); getBirthday = getBirthday.Substring(0, getNum); sb.Append("<tr>").Append("<td>").Append(row["Tname"]).Append("</td>") .Append("<td>").Append(getBirthday).Append("</td>") .Append("<td>").Append(row["Tphone"]).Append("</td>") .Append("<td>").Append(row["Temail"]).Append("</td>") .Append("<td><a href='../ManagementChange/Delete.ashx?id=").Append(row["Id"]).Append("&method=Teacher'>删除</td>") .Append("<td><a href='../ManagementChange/TeacherEditAddNew.ashx?action=edit&id=").Append(row["Id"]).Append("'>编辑</td>") .Append("</tr>"); } html = html.Replace("*table", sb.ToString()); context.Response.Write(html); } ``` 3.配置修改文件夹(ManagementChange) 知识点讲解:首先拿到渲染的页面,通过公用类将页面内容获取为字符串,查询数据库获取数据并拼接为我们想展示效果,最后对标记的字符串进行替换并输出为html页面或者执行数据库语句再重定向到对应的管理页面。 (1)学员信息的修改 (1 StudentEditAddNew.html ``` <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>*actionName学生信息</title> </head> <body> <form *action method="post"> 姓名:<input type="text" name="name" value="*name" /> 性别:<select name="gender"> *sex </select> 生日:<input type="datetime" name="birthday" value="*birthday" /> 身高:<input type="text" name="height" value="*height" /> 所属班级:<select name="class"> *class </select> <input type="checkbox" name="ability" *value />特长生 <br /> <input type="submit" value="确定" name="btnTrue" /> </form> </body> </html> ``` (2 StudentEditAddNew.ashx ``` public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/html"; string action = context.Request["action"]; string btnTrue = context.Request["btnTrue"]; string html = CommonHelper.ReadHtml("./StudentEditAddNew.html"); if (btnTrue == null) { DataTable dt = SqlHelper.GetTable("select s.Id,s.Sname name,s.Ssex sex,s.Sbirthday birthday,s.Sheight height,s.Sability ability,s.Sclass class,c.Cname from student s left join class c on s.Sclass=c.Cname"); DataTable dtc = SqlHelper.GetTable("select Cname from class"); if (action == "addNew") { StringBuilder sb = new StringBuilder(); foreach (DataRow row in dtc.Rows) { sb.Append("<option value='").Append(row["Cname"]).Append("'>").Append(row["Cname"]) .Append("</option>"); } html = html.Replace("*actionName", "新增").Replace("*name", "").Replace("*birthday", DateTime.Now.ToString("yyy/MM/dd")) .Replace("*height", "").Replace("*class", sb.ToString()).Replace("*sex", "<option value='男'>男</option><option value='女'>女</option>"); context.Response.Write(html); }//添加 if (action == "edit") { int id = Convert.ToInt32(context.Request["id"]); //这里怎么避免用户输入id的bug?ExecutScaler看id的返回值 object numberId = SqlHelper.ExecuteScaler("select * from student where Id=" + Convert.ToString(id)); if (numberId == null) { CommonHelper.OutputError("id不正确!"); } else { DataTable dte = SqlHelper.GetTable("select * from student where Id=@id", new SqlParameter("@id", id)); if (dte.Rows.Count != 1)//避免其出现多行和该id不存在 { CommonHelper.OutputError("action错误"); } DataRow row = dte.Rows[0]; string name = (string)row["Sname"]; string gender = Convert.ToString((bool)row["Ssex"] == true ? "男" : "女"); string getBirthday = ((DateTime)row["Sbirthday"]).ToString("yyy/MM/dd"); int height = (Int32)row["Sheight"]; string Sclass = (string)row["Sclass"]; string ability = Convert.ToString((bool)row["Sability"] == true ? "checked" : ""); StringBuilder sb = new StringBuilder(); foreach (DataRow dr in dt.Rows) { int getId = (int)dr["Id"]; if (getId == id) { sb.Append("<option value='").Append(dr["Cname"]).Append("' selected>").Append(dr["Cname"]) .Append("</option>"); } else { sb.Append("<option value='").Append(dr["Cname"]).Append("'>").Append(dr["Cname"]) .Append("</option>"); } } html = html.Replace("*actionName", "编辑").Replace("*name", name).Replace("*height", height.ToString()).Replace("*birthday", getBirthday).Replace("*value", ability).Replace("*class", sb.ToString()); if (gender == "女") { html = html.Replace("*sex", "<option value='女'>女</option><option value='男'>男</option>"); } else { html = html.Replace("*sex", "<option value='男'>男</option><option value='女'>女</option>"); } html = html.Replace("*action", "action='../ManagementChange/StudentEditAddNew.ashx?newAction=edit&id=*newId'"); html = html.Replace("*newId", id.ToString()); context.Response.Write(html); }//id存在else }//编辑 }//ifbtnTrue不为null else { string newAction = context.Request["newAction"]; string name = context.Request["name"]; bool sex = context.Request["gender"] == "男" ? true : false; DateTime birthday = Convert.ToDateTime(context.Request["birthday"]); int height = Convert.ToInt32(context.Request["height"]); string getclass = context.Request["class"]; bool ability = context.Request["ability"] == "on" ? true : false; if (newAction == "edit") { int id = Convert.ToInt32(context.Request["id"]); //这里怎么避免用户输入id的bug?ExecutScaler看id的返回值 object numberId = SqlHelper.ExecuteScaler("select * from student where Id=" + Convert.ToString(id)); if (numberId == null || (int)numberId > 1) { CommonHelper.OutputError("id不正确或存在异常!"); } int i = SqlHelper.ExecuteNonQuery("update student set Sname=@name,Ssex=@sex,Sbirthday=@birthday,Sheight=@height,Sability=@ability,Sclass=@getClass where Id=@id", new SqlParameter("@id", id), new SqlParameter("@name", name), new SqlParameter("@sex", sex), new SqlParameter("@birthday", birthday), new SqlParameter("@height", height), new SqlParameter("@ability", ability), new SqlParameter("@getClass", getclass)); } if (action == "addNew") { SqlHelper.ExecuteNonQuery("insert into student(Sname,Ssex,Sbirthday,Sheight,Sability,Sclass) values(@name,@sex,@birthday,@height,@ability,@getClass)", new SqlParameter("@name", name), new SqlParameter("@sex", sex), new SqlParameter("@birthday", birthday), new SqlParameter("@height", height), new SqlParameter("@ability", ability), new SqlParameter("@getClass", getclass)); } context.Response.Redirect("../Management/StudentManagement.ashx"); } } ``` (2)班级信息的修改 (1 ClassEditAddNew.html ``` <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>*actionName班级信息</title> </head> <body> <form *action method="post"> 班级名:<input type="text" name="name" value="*name" /> 班级号:<input type="text" name="number" value="*number" /> 班主任:<select name="teacher"> *teacher </select> <input type="submit" value="确定" name="btnTrue" /> </form> </body> </html> (2 ClassEditAddNew.ashx public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/html"; string action = context.Request["action"]; string btnTrue = context.Request["btnTrue"]; string html = CommonHelper.ReadHtml("./ClassEditAddNew.html"); if (btnTrue == null) { DataTable dt = SqlHelper.GetTable("select c.Id,c.Cname name,c.Cnumber number,c.Cteacher teacher,t.Tname from class c left join teacher t on c.Cteacher=t.Tname"); DataTable dtt = SqlHelper.GetTable("select Tname from teacher"); if (action == "addNew") { StringBuilder sb = new StringBuilder(); foreach (DataRow row in dtt.Rows) { sb.Append("<option value='").Append(row["Tname"]).Append("'>").Append(row["Tname"]) .Append("</option>"); } html = html.Replace("*actionName", "新增").Replace("*name", "").Replace("*number", "") .Replace("*teacher", sb.ToString()); context.Response.Write(html); }//添加 if (action == "edit") { int id = Convert.ToInt32(context.Request["id"]); //这里怎么避免用户输入id的bug?ExecutScaler看id的返回值 object numberId = SqlHelper.ExecuteScaler("select * from class where Id=" + Convert.ToString(id)); if (numberId == null) { CommonHelper.OutputError("id不正确!"); } else { DataTable dte = SqlHelper.GetTable("select * from class where Id=@id", new SqlParameter("@id", id)); if (dte.Rows.Count != 1)//避免其出现多行和该id不存在 { CommonHelper.OutputError("action错误"); } DataRow row = dte.Rows[0]; string name = (string)row["Cname"]; string number = Convert.ToString(row["Cnumber"]); string teacher = (string)row["Cteacher"]; StringBuilder sb = new StringBuilder(); foreach (DataRow dr in dt.Rows) { int getId = (int)dr["Id"]; if (getId == id) { sb.Append("<option value='").Append(dr["teacher"]).Append("' selected>").Append(dr["teacher"]) .Append("</option>"); } else { sb.Append("<option value='").Append(dr["teacher"]).Append("'>").Append(dr["teacher"]) .Append("</option>"); } } html = html.Replace("*actionName", "编辑").Replace("*name", name).Replace("*number", number).Replace("*teacher", sb.ToString()); html = html.Replace("*action", "action='../ManagementChange/ClassEditAddNew.ashx?newAction=edit&id=*newId'"); html = html.Replace("*newId", id.ToString()); context.Response.Write(html); }//id存在else }//编辑 }//ifbtnTrue不为null else { string newAction = context.Request["newAction"]; string name = context.Request["name"]; string number = context.Request["number"]; string teacher = context.Request["teacher"]; if (newAction == "edit") { int id = Convert.ToInt32(context.Request["id"]); //这里怎么避免用户输入id的bug?ExecutScaler看id的返回值 object numberId = SqlHelper.ExecuteScaler("select * from class where Id=" + Convert.ToString(id)); if (numberId == null || (int)numberId > 1) { CommonHelper.OutputError("id不正确或存在异常!"); } int i = SqlHelper.ExecuteNonQuery("update class set Cname=@name,Cnumber=@number,Cteacher=@teacher where Id=@id", new SqlParameter("@id", id), new SqlParameter("@name", name), new SqlParameter("@number", number), new SqlParameter("@teacher", teacher)); } if (action == "addNew") { SqlHelper.ExecuteNonQuery("insert into class(Cname,Cnumber,Cteacher) values(@name,@number,@teacher)", new SqlParameter("@name", name), new SqlParameter("@number", number), new SqlParameter("@teacher", teacher)); } context.Response.Redirect("../Management/ClassManagement.ashx"); } } ``` (3)教室信息的修改 (1 TeacherEditAddNew.html ``` <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>*actionName教师信息</title> </head> <body> <form *action method="post"> 姓名:<input type="text" name="name" value="*name" /> 邮箱:<input type="text" name="email" value="*email" /> 生日:<input type="datetime" name="birthday" value="*birthday" /> 手机:<input type="text" name="phone" value="*phone" /> <input type="submit" value="确定" name="btnTrue" /> </form> </body> </html> ``` (2 TeacherEditAddNew.ashx ``` public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/html"; string action = context.Request["action"]; string btnTrue = context.Request["btnTrue"]; string html = CommonHelper.ReadHtml("./TeacherEditAddNew.html"); if (btnTrue == null) { DataTable dt = SqlHelper.GetTable("select * from teacher"); if (action == "addNew") { html = html.Replace("*actionName", "新增").Replace("*name", "").Replace("*birthday", DateTime.Now.ToString("yyy/MM/dd")) .Replace("*email", "").Replace("*phone", ""); context.Response.Write(html); }//添加 if (action == "edit") { int id = Convert.ToInt32(context.Request["id"]); //这里怎么避免用户输入id的bug?ExecutScaler看id的返回值 object numberId = SqlHelper.ExecuteScaler("select * from teacher where Id=" + Convert.ToString(id)); if (numberId == null) { CommonHelper.OutputError("id不正确!"); } else { DataTable dte = SqlHelper.GetTable("select * from teacher where Id=@id", new SqlParameter("@id", id)); if (dte.Rows.Count != 1)//避免其出现多行和该id不存在 { CommonHelper.OutputError("action错误"); } DataRow row = dte.Rows[0]; string name = (string)row["Tname"]; string getBirthday = ((DateTime)row["Tbirthday"]).ToString("yyy/MM/dd"); string email = (string)row["Temail"]; string phone = (string)row["Tphone"]; StringBuilder sb = new StringBuilder(); html = html.Replace("*actionName", "编辑").Replace("*name", name).Replace("*email", email).Replace("*birthday", getBirthday).Replace("*phone", phone); html = html.Replace("*action", "action='../ManagementChange/TeacherEditAddNew.ashx?newAction=edit&id=*newId'"); html = html.Replace("*newId", id.ToString()); context.Response.Write(html); }//id存在else }//编辑 }//ifbtnTrue不为null else { string newAction = context.Request["newAction"]; string name = context.Request["name"]; DateTime birthday = Convert.ToDateTime(context.Request["birthday"]); string phone = context.Request["phone"]; string email = context.Request["email"]; if (newAction == "edit") { int id = Convert.ToInt32(context.Request["id"]); //这里怎么避免用户输入id的bug?ExecutScaler看id的返回值 object numberId = SqlHelper.ExecuteScaler("select * from teacher where Id=" + Convert.ToString(id)); if (numberId == null || (int)numberId > 1) { CommonHelper.OutputError("id不正确或存在异常!"); } int i = SqlHelper.ExecuteNonQuery("update teacher set Tname=@name,Tbirthday=@birthday,Tphone=@phone,Temail=@email where Id=@id", new SqlParameter("@id", id), new SqlParameter("@name", name), new SqlParameter("@birthday", birthday), new SqlParameter("@phone", phone), new SqlParameter("@email", email)); } if (action == "addNew") { SqlHelper.ExecuteNonQuery("insert into teacher(Tname,Tbirthday,Tphone,Temail) values(@name,@birthday,@phone,@email)", new SqlParameter("@name", name), new SqlParameter("@birthday", birthday), new SqlParameter("@phone", phone), new SqlParameter("@email", email)); } context.Response.Redirect("../Management/TeacherManagement.ashx"); } } ``` (4)信息的删除Delete.ashx ``` public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/html"; int id = Convert.ToInt32(context.Request["id"]); string method = context.Request["method"]; SqlHelper.ExecuteNonQuery(string.Format("delete from {0} where Id = @Id",method), new SqlParameter("@Id", id)); context.Response.Redirect(string.Format("../Management/{0}Management.ashx", method));//删除完成后重定向回列表页面 } ``` (5)错误页Error.html ``` <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>错误</title> </head> <body> <h1 style="color:red;">*message</h1> </body> </html> ``` 温馨提示:这样我们的一个增删改查Demo就完成了,这一部分内容比较多,而且属于核心知识,大家一定要掌握好。 数据库备份在了项目中请自行还原,还原步骤如图:  (1)选中数据库右键(2)点击还原数据库(3)选设备(4)按三个点(5)点击添加(6)选择你还原的数据库文件(7)一路确定。   (8)提示成功还原并出现数据库,代表完成了。 #####3.源码 [源代码](https://jiyuwu.lanzouq.com/iqwQ402zy6mf "源代码") #### 课程附件 [附件](https://movie.jiyuwu.com/upload/VIP/Video/admin//2018/8/26/8801bf26e1dc06fa5ba11c8d22202da8.zip "附件")
上一篇
下一篇
版权所有:机遇屋在线 Copyright © 2021-2025 jiyuwu Co., Ltd.
鲁ICP备16042261号-1