欢迎光临散文网 会员登陆 & 注册

C#实际案例分析(最终弹)——By 流星

2022-01-31 19:43 作者:ForeverMeteor  | 我要投稿

实验六

题目要求

基于Asp.Net Core进行网页编程,从数据库中读取学生看书的数据,并展示到网页中。要求先展示列表,然后点击具体项目,进行展示。可进行一定的数据汇总。

环境设置

操作系统: Windows 10 x64

SDK: .NET Framework 4.7.2

IDE: Visual Studio 2019

题意分析

俗话说,题目越短越困难。还是像以往一样,我们把要求拆解来看,具体有以下几个要求:

①基于Asp.Net Core进行网页开发
②从数据库中读取数据
③将数据展示到网页中
④先展示列表,然后点击具体项目进行展示
⑤可进行一定的数据汇总

可以看到,其中的①和②就是我们最大的核心功能,也正是前端后端的内容。将①②③串接在一起就是实验的主体,④和⑤是附加要求。
对于前端内容①,我们需要掌握Asp.Net Core的基本开发方式,掌握MVC模式(模型-视图-控制器模式)的基本架构和使用,并在这一模式中完成数据库的操作和前端页面的展示。
对于后端内容②,我们需要掌握数据库的基本组织形式和SQL语言的基本使用。本次实验使用开源的MySQL数据库,通过MySQL进行数据库、表的建立和加入数据,建好的数据表供网页直接读取。具体的模式我们将在下面展开。
从ASP.Net Core的性质出发,本次实验使用的是前后端不分离的开发模式,即通过ASP.Net Core现场读取数据库并展示在动态网页之中。当下流行的也是更高效率开发模式是前后端分离的开发模式,即前后端只使用一个例如json的文件进行交互:前端向后端发送请求并获取文件然后解析。限于篇幅本文不再赘述。

后端·数据库

数据库概述

数据库,顾名思义,就是用来存放数据的地方。从精确的定义来看,数据库是指以一定方式存储在一起,能为多个用户共享,具有尽可能小的冗余度,并且与应用程序彼此独立的数据集合,用于存储结构化数据。数据组织有多种数据模型,目前主要的数据模型是关系数据模型,以关系模型为基础的数据库就是关系型数据库,也是目前使用最广泛的数据库。当下流行的各个数据库,例如Oracle、Microsoft SQL Server、Access和MySQL等等,都是关系型数据库。简单来说,关系模型指的就是二维表格模型,而一个关系型数据库就是由二维表及其之间的联系所组成的一个数据组织。

SQL

有了数据库之后,自然而然想到的是如何去操作它。结构化查询语言(Structured Query Language),即SQL,是源自于IBM公司,后被采纳为国际标准的关系型数据库的查询语言。它操作简单易上手,许多数据库都支持,当然包括我们这个实验用到的MySQL数据库。SQL语言包括查询,操纵,定义和控制等几个部分,通过命令动词来实现。我们更为熟知的是CRUD(增查改删,Create Retrieve Update Delete),当然也包括在这些命令中。我们将在接下来详细地使用SQL语言来构建和读取我们的数据库。

C#中的SQL

要在C#中使用SQL对数据库进行操作,可没有这么简单。换句话说,我们不能像在MySQL的命令窗口里输入指令那样直接在C#的控制台里使用SQL,而必须通过程序对数据库进行连接,使用字符串表示命令并通过C#语句调用它们,最后再退出。不同的数据库使用不同的前缀语句,例如MySQL数据库对应的语句是MySqlxxx,并要引入MySql.Data.MySqlClient包;而Microsoft SQL Service使用的语句是OleDbxxx等。我们将在下面的流程里看到它的详细使用方法。

前端·ASP.NET Core

前端基础知识·HTML和JavaScript

为了将数据展示在浏览器中,我们需要运用HTMLJavaScript与用户进行交互。
超文本标记语言(Hyper Text Markup Language),即HTML,是一种标记语言,它通过标记符号来标记要显示的网页中的各个部分。网页文件本身是一种文本文件,通过在文本文件中添加标记符,可以告诉浏览器如何显示其中的内容。浏览器按顺序阅读网页文件,然后根据标记符解释和显示其标记的内容。简单来说,我们通过输入不同的标记来完成不同的功能。而这些标记不同于XML,是已经规定好的,我们运用这些标记的组合就像使用指令一样控制网页的长相。我们将在接下来看见它们的使用方式。
上面提到的HTML只能完成网页的展示部分,但是我们能看见的绝大部分网页都是能够跟用户进行多姿多彩的交互的。这怎么办?为了完成这些交互,我们需要使用JavaScript这个脚本语言。脚本语言的特性是“随调随用”,也就是解释型或者即时编译型语言。它不同于大量的后端语言是编译之后再执行,而是在网页运行的过程中一句一句执行。这样的特性可以帮助我们实现在网页运作中的各种各样的功能。在实际开发中,JS和HTML结合起来完成了展示和人机交互的基本功能。
除了HTML和JavaScript,在前端的开发中时常运用到的还有CSS(层叠样式表,Cascading Style Sheets)来完成各种各样绚丽的动态效果。本实验的功能使用不到它,有兴趣的读者可以自行查找资料进行了解。

ASP.NET Core概述

动态服务器页面(Active Server Pages),即ASP,是微软公司开发的服务器端脚本环境,可用来创建动态交互式网页并建立强大的web应用程序。当服务器收到对ASP文件的请求时,它会处理包含在用于构建发送给浏览器的HTML网页文件中的服务器端脚本代码。而.NET平台我们已经很熟悉了,是微软开发的开发平台。.NET Core是.NET Framework的新一代版本,是微软开发的第一个具有跨平台(Windows、Mac OSX、Linux)能力的应用程序开发框架。二者结合起来就是ASP.NET Core,它是基于.NET Core的Web开发框架,是对ASP.NET的再开发和优化。有兴趣的读者可以自行查找并了解他们的历史,本文就不再赘述了。

MVC(模型-视图-控制器,Model-View-Controller)

MVC是一种构建Web应用的模式,简单来说就是这个网页或者说Web应用是怎么构建的,怎么运作的。其应用几乎遍及所有的Web框架,而不仅仅是在我们实验用的Asp.Net Core中。就连iOS和Android上的移动应用也是MVC的一个变种。拆开来看,MVC的三个组成部分有如下的功能:

模型:负责应用程序中用于处理应用程序数据逻辑的部分,通常模型对象负责在数据库中存取数据。在Asp.Net Core中,模型可以分为两种:以xxxItem命名的模型负责记录部分,记录的是保存在数据库中的条目;以xxxViewModel命名的模型负责与视图相结合,发送到浏览器供用户查看。

视图:是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。简单来说就是把已经存好的数据呈现给用户。在Asp.Net Core中,视图是用Razor语言书写的,它存储在后缀为.cshtml的特殊文件中。关于Razor语言我们将在下面进行介绍。

控制器:是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。也就是说控制器是负责人机交互的“窗口”,它处理用户(端)的输入并送交给相应的代码进行处理。

Razor·HTML和C#的结合体

上面提到了Razor这种语言。其实,他就是HTML和C#(也可以是VB)的混合版本。Razor使用“@”符号来区别HTML标记和C#代码。以@开头的变量或是头尾用@标记的均被识别为C#代码。而这C#代码之中还可以嵌套HTML标记,比如放入表单元素之中(<td><td>)。是不是很神奇?它在一定程度上可以取代部分JS代码的功能。我们可以在下面看到这个东西的实际用途。需要注意的是,这个语言是微软特地为ASP系列的网页开发而制造的,纯前端的开发是用不了它的。

数据从何而来?

数据当然是从数据库读取啦。本次实验的需求比较简单,于是我们可以直接把读取数据库的任务交给Controller,即直接在控制器Controller当中读取数据库的内容,然后存到模型Model(xxxItem)里面。在更加专业化,更加层次化结构化的ASP.NET Core开发中,我们会再把MVC改造成不同的层次以达到展示和与后端交流分开的作用。这时候就会出现:一个由控制器和视图构成的表示层,用来处理用户的交互;一个包含了业务逻辑和数据库代码的服务层,跟数据库交流的任务就会交给这个服务层。读者可以自行查找相关的资料并了解,本次实验只和大家交流最简单的开发工作。

完整代码

后端代码(实验六 第二题 后端\Program.cs):建立数据库并写入数据


前端代码(实验六 第二题 前端\Controllers\HomeController.cs):初始创立时的页面

前端代码(实验六 第二题 前端\Controllers\TestController.cs):自写的控制器,用以读取数据库和存放数据

前端代码(实验六 第二题 前端\Models\TestItem.cs):提供了数据访问的接口

前端代码(实验六 第二题 前端\Models\TestViewModel.cs):与视图结合提供给用户

前端代码(实验六 第二题 前端\Views\Home\Index.cshtml):初始创立时的页面

前端代码(实验六 第二题 前端\Views\Home\Privacy.cshtml):初始创立时的页面

前端代码(实验六 第二题 前端\Views\Test\Index.cshtml):自写的页面,包含了对模型中数据的筛选和展示

代码片段分析

后端·建立数据库

由于无法像在控制台那样直接操作数据库,我们只能通过包提供的字符串的形式来通过C#指令对数据库进行连接和其他操作。下面的代码也是相同的道理。

对于非查询的语句,包提供了ExecuteNonQuery()这一指令进行操作,操作的SQL指令就是写在CommandText中的字符串。而查询语句是数据库操作中最常用的语句,且查询的方式丰富多彩,比如下面的这一块代码:

MySQL在C#的包中提供了两种查询语句的方式,其中一种便是上面提供的ExecuteReader()。这一语句的作用是创建一个读取器对象,这个读取器对象就像一个迭代器一样,逐行读出SQL命令获取的数据并以数组的形式返回,所以我们可以通过下标的方式来获取每个字段的内容。当然,上面的代码只是在调试后端的时候用得到,在前端读取数据的时候是要稍加改造的,我们会在后面看到。

前端

TestController.cs中

这一段代码是将前端的内容稍加改造用以读取数据库。不同的地方在于,它将数据先放进一个临时的对象数组,而后将数组传入模型之中存储。实际测试中,return View(new TestViewModel { Contents = contents });这样创建新对象数组的方式是必要的,否则会导致问题,而问题的原因目前仍未究明。Index函数是供页面加载时直接读取的函数,而不用再增加子目录。

Test\Index.cshtml中

上面这段是纯粹的HTML语言,用以创建表头(thead),也就是表格的第0行。其中包含了一些select控件,也就是下拉菜单,它的元素是option,也就是各个选项。控件的onchang函数是在控件的内容改变的时候会触发的函数,函数内容写在了JavaScript脚本之中,我们会在接下来看到。
到这里,数据筛选,也就是要求④的初步思路已经有所窥见了:我们会利用JS脚本,像开发C#程序一样对数据进行筛选,然后再返回给表格显示出来。这些数据都已经是被读取之后放进缓冲区之中的了,而不是现场调取数据库。
仅仅有上面HTML的文本是还不够的,我们还需要将内容一个个添加到表格的cell,也就是单元里面,这时候Razor就派上用场了:

前面加了@符号的都是C#的语法或者变量,而带<>的都是HTML语法。可以看到,C#的变量被嵌入到了单元格之中,而单元格又被嵌入到了foreach循环之中,变相达到了动态创建表格的效果。当然,以上功能通过JavaScript应该也是能够达到的,但是要用JS和C#导出的数据打交道就显得有些麻烦了,Razor正好弥合了这二者的空缺;接下来我们会看到纯HTML条件下JS发挥的作用。我们接着往下看。

JS脚本要写在<script><script>标签之中。这一段文字上下代码的顺序跟写在程序的是相反的,因为从逻辑上来看,应当先实现的是完成所有数据的汇总之后展示,而后点击下拉列表进行筛选。前者是在网页运行时依据脚本的编写次序来运行,而后者要通过调用函数来实现。更好的处理方式是将函数的实现放在HTML的头部,也就是<head></head>标签之中。
现在来分析一下这部分脚本的作用。在先前的代码中已经通过Razor将数据库内容放到HTML表格里了,但是这些内容没有进入JS的存储空间中,所以我们要通过HTML表格这一中介将数据读到一个全局数组变量里面,再对它进行筛选。全局数组里面是存储的数据是JS对象,而JS的对象接触过JSON(JavaScript Object Notation)的同学就很熟悉了:一个{}中囊括了一些键值对,其中键就是属性,值就是这个属性对应的值,刚好拿来装学生的字段信息。我们一边将每行的字段从表格之中找出来,然后存到对象里面(比如oneStudent.number = tableElement.rows[i].cells[0].innerText),一边将这些选项放进下拉框select当中。这当中已经包含了去重的过程为了达到去重的效果,我们为要筛选的字段开一个辅助数组,比如var qNumber = new Array(),将没有插入过select下拉框的对象插入其中,同时又插入下拉框中。其中用到的indexOf函数事实上承担了筛选的作用,若其返回-1则表示该对象不在数组之中。
值得一提的是,JavaScript是一种弱类型语言,因而所有变量都以var声明。提到这个是因为经常使用到的document.getElementById()是功能非常强大的函数,能够在页面范围内根据Id值抓取不同的对象。这个Id值就好像C#中的变量名,可以用以标识不同种类的控件。
接下来的部分就全是JS函数部分了,也是这个实验最终的部分。

以上就是三个子功能函数的内容。首先是将表格的内容全部删除。我们能够在此大胆删掉表格的原因是我们已经将所有的内容按照对象加入了全局数组之中。删除的原理是获取表格所有的行,并且逐行删除。这里要注意两点:其一,从尾部开始删起,以防止循环变量下标和行数的改变影响删除次序(想象一下跳着删);其二,第0行是表头,真正的内容是从第1行开始的,删除时要注意i>0
第二个函数的内容是从外部获取要筛选的内容并进行筛选,返回一个筛选完毕的数组。这个判定的信息由总的函数提供,来自于select框的选定内容,提取的方式在下面的代码可以看见。在select下拉框中有一个特殊的符号"*",也就是通配符。通配符表示不对当前字段的内容做筛选限制。那么它在判定条件之中是如何表现的呢?显然,它对于传入的任何条件都返回真,自然而然地想到用或条件来实现。而将这些带或逻辑的判定表达式用与运算符连接起来就是总的判定条件了,也就是代码中如下的部分。

第三个函数则是创建新的表格并将返回的筛选过的数组插入其中。插入的方式是逐行插入,每行中逐单元插入,也就是逐列插入。这些table控件自带的函数形式上比较简单,这里就不再赘述了,能掌握使用方式就行了。
接下来就是把这些子函数全部拼装起来,变成一个供调用的总函数:

以前两行为例,由于select只能获取到被选中项的下标,我们需要通过下标从options数组中来获取被选中的option。而option是一个对象,我们要的筛选方式是通过字符串来筛选,于是通过value值获取它们的文字。注意,这只能在未在标签中指定value值的时候使用,若已指定value值,可使用innerText来获取。获取各个select框里用户要求的筛选条件之后将它们传入ChooseCondition函数中,再运行各个子函数就能达到我们想要的目标了。
那么,这个函数将在什么时候调用呢?我们回到最开始制造表格时的代码:

这个onchange函数就是用以调用最终的ChooseSelect()函数,来实现在每次完成任意一个下拉框的改变之后改变整张表格的内容。

至此。我们层层解析,步步为营,终于达到了实验要求的目标。接下来进入本实验,也是我们最后一个实验的特色环节:

演示

这是本实验的特色环节。这次实验大部分在于前端,而我们又不像之前那样直接使用窗体进行开发而需要借助浏览器展示。这是一个所见即所得的项目,我们将从数据库开始,逐步展示我们这次实验的所有界面。
在运行了后端代码之后,我们直接到数据库窗口(cmd),通过select * from studentdata指令查看已经插好的数据库(表):

可以看到,数据已经被写入数据库了。我们返回DOS界面,将目录转移到项目文件夹下,输入指令dotnet watch run运行整个项目。当然,也可以在VS中直接启动,在IIS中运行。


可以看到,在运行web应用之后直接进入了home界面,我们在地址栏中追加/test来实现对TestController的Index函数的访问,进而展示到浏览器之中。

可以看到我们已经进入了含有表格的页面,这里展示了所有的数据。我们可以通过调整不同的筛选条件选择我们想要的条目

如果选择互斥的条件的话……

可以看到它变成了一张空表,情理之中。
至此,我们已经完成了这个实验所有内容的展示。

总结

通过本次实验,我们了解了关系型数据库的基本组织形式,掌握了SQL语言的基本内容和使用方式,并完成了往其中添加数据和查找数据的功能。在前端内容方面,我们学习了HTML、JavaScript等前端基础知识,了解了Asp.Net Core的基本组织结构和MVC开发模式。通过以上知识完成了一个简单Web应用的开发。

当然这个实验是非常简单的MVC开发模式,与真正专业化的开发相比还难以望其项背。比如,就算在前后端不分离的场景下,应该也存在某种方式能够让前端给后端发送指令请求并查询数据库而后返回,而不是使用通过JS操作缓存区的数据这样效率较低的方式。数据库的优势就在于强大的数据组织能力。其次,本实验本可以分层完成,即前文提到的分为表示层和服务层等,这样能够使得程序更加模块化。最后,我们可以通过Asp.Net Core提供的其他方式完成对数据库更高效的访问,而非使用MySql.Data.MySqlClient这一包。

回顾

通过这学期的C#学习,我们从最开始的控制台界面开发,到窗体应用开发,到委托事件反射,再到多线程和互斥,最后到Web应用开发,可以说是学到了不少的东西。笔者也从一个一无所知的小白,一路走到了具有一定开发基础的研习者了。当然,软件开发的途径远不止这些,软件开发也绝非C#这一条路,但是通过本学期的C#学习,我们能够领略到软件开发的魅力和基本模式,基本知识。软工路且长,希望日后能够学到更多深刻,实用,有趣的开发内容。在文章的最后,要感谢一直陪伴和指导我们的赖永炫教授,尽心尽力的助教老师,身边各位亲爱的同学们,以及在崎岖道路上不断攀登的自己。
以上,就是本次实验报告的,
所有内容。
祝阅读到此的各位小伙伴2022快乐!

参考文献

李辉 等.数据库系统原理及MySQL应用教程:机械工业出版社,2015

李春葆,曾平,喻丹丹.C#程序设计教程(第3版):清华大学出版社,2015

赖永炫.厦门大学移动计算与数据分析实验室,Mobile Computing & Data Analysis

Copyright @ 2022, Bilibili: ForeverMeteor, all rights reserved. 

C#实际案例分析(最终弹)——By 流星的评论 (共 条)

分享到微博请遵守国家法律