·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> 网站建设开发 >> ASP.NET网站开发 >> 7 天玩转 ASP.NET MVC — 第 3 天
我们假定你在开始学习时已经阅读了前两天的学习内容。在第 2 天我们完成了关于显示 Employees 列表的项目。
在第三天,我们将会通过介绍数据访问层和数据入口将它升级到一个新的层次。
在真实场景的项目中,如果没有 Database,那么这个项目是未完成的。在我们的项目中,我们还没有谈到数据库。第三天的首个 Lab 将会学习数据库和数据库层。
这里我们将使用 SQL Server 和 Entity Framework 来创建 Database 和 Database 访问层。
这是一个 ORM 工具。ORM 代表的是 Object Relational Mapping。即:对象关系映射。
在 RDBMS 领域中,我们所谈论的 Tables 表格和 Columns 列的这些方面,在 .NET 领域(面向对象领域)中被称为 Classes 类,对象和属性。
当我们思考任何有关数据驱动应用的方式时,都可以得出以下两种方式:
书写代码来和数据库打交道(被称为数据访问层和数据库逻辑)
书写代码来将数据库数据映射到面向对象中,反之亦然。
ORM 是一个工具,可以自动做如上两件事。Entity Framework 是微软的 ORM 工具。
在 Entity Framework 中,我们可以使用如下三种的任意方法:
Database First 方法。创建一个有表,列和关系的数据库。Entity Framework 将会生成对应的 Model 类(业务实体)和数据访问层代码。
Model First 方法。在这个方法中,Model 类和它们之间的联系将会被 Model 设计者在 Visual Studio 中被手动定义。然后 Entity Framework 会自动创建数据访问层和拥有表、列以及关系的数据库。
Code First 方法。在这个方法中,手动创建 POCO 类。这些类中的关系将会被代码所定义。当应用第一次执行时,Entity Framework 将会自动在数据库服务器上创建数据访问层和拥有表、列以及关系的数据库。
什么是 POCO 类?
POCO 代表的是「Plain Old CLR Objects」。POCO 类代表的是我们所创建的简单 .NET 类。在我们之前的例子中, Employee 类是一个简单的 POCO。
第一步:创建数据库
连接 SQL Server 然后创建一个新的数据库,命名为「SalesERPDB」。
第二步:创建 ConnectionString
打开 Web.config 文件,然后在 Configuration 区域内添加如下片段:
<connectionStrings> <add connectionString="Data Source=(local);Initial Catalog=SalesERPDB;Integrated Security=True" name="SalesERPDAL" PRoviderName="System.Data.SqlClient"/></connectionStrings>
第三步:添加 Entity Framework 引用
右击项目-> 管理 Nuget 包。搜索 Entity Framework,然后点击安装。
第四步:创建数据访问层
在根目录下创建一个新文件夹,命名为「DataaccessLayer」,然后在里面创建一个新的类,命名为「SalesERPDAL」。
在类顶部写引用声明如下 using System.Data.Entity;
继承 DbContext 的类「SalesERPDAL」
public class SalesERPDAL: DbContext {}
第五步:为 Employee 类创建主键
打开 Employee 类并在类顶部声明如下:
using System.ComponentModel.DataAnnotations;
在 Employee 类中添加 EmployeeId 属性,然后将其标注为 Key 属性。
public class Employee { [Key] public int EmployeeId { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public int Salary { get; set; }}
第六步:定义映射
在「SalesERPDAL」类中添加如下声明语句:
using Webapplication1.Models;
在 SalesERPDAL 类中重写 OnModelCreating 方法。
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<employee>().ToTable("TblEmployee"); base.OnModelCreating(modelBuilder);}
注意:上述代码中的片段「TblEmployee」代表的是表名。在运行时讲自动被创建。
第七步:在数据库中创建 Employees 属性
在「SalesERPDAL」类中创建一个新属性,命名为 Employee,如下所示:
public DbSet<employee> Employees{get;set;}
DbSet 将会展示所有可以在数据库中查询到的 Employees。
第八步:改变业务层代码,从数据库中读取数据
打开 EmployeeBusinessLayer 类,在顶部加上声明如下:
using WebApplication1.DataAccessLayer;
现在改变 GetEmployees 方法如下:
public List<employee> GetEmployees() { SalesERPDAL salesDal = new SalesERPDAL(); return salesDal.Employees.ToList();}
第九步:执行并测试
按下 F5,并执行应用。
现在的数据库中,我们没有任何的 Employees,所以我们看见的是一个空白的 Grid。
查看数据库,现在我们可以在 TblEmployee 表中看到所有的列。
第十步:插入测试数据
向 TblEmployee 表中插入一些测试数据。
第十一步:执行并测试应用
按下 F5 并再次运行应用。
什么是 DbSet?
DbSet 简单地表示了可以从数据库中查询到的实体集合。当我们再次写一个 Linq 查询时,DbSet 对象会对查询进行内存转换,然后触发数据库。
在我们的例子中,「Employee」是一个 DbSet,它承载了所有可以从数据库中查询到的 Employee 实体对象。每一次我们尝试访问「Employees」时,它都将从“TblEmployee”表中获取记录,然后将其转换为「Employees」对象并返回集合。
数据库连接串和数据访问层是如何连接的?
Mapping 通过名称来实现。在我们的例子中,ConnectionString 名称和数据访问层类的名称是一样的,即「SalesERPDAL」,因此它们是自动映射的。
我们可以更改 ConnectionString 的名称吗?
答案是肯定的。在这个例子中,我们需要在数据访问层类中定义一个构造函数如下:
public SalesERPDAL():base("NewName") {}
我们需要做几个改变,使得所有是有组织和有意义的。
第一步:重命名
「TestController」换名为 「EmployeeController」。
GetView 行为方法改为 Index。
Test 文件夹(Views 文件夹下) 改为 Employee
「MyView」视图改为「Index」。
第二步:从 EmployeeListViewModel 中删除 UserName 属性
第三步:从视图中删除 UserName
打开 View/Employee.Index.cshtml 视图,然后从中删除 UserName。
简单来说,就是删除如下代码:
Hello @Model.UserName <hr />
第四步:在 EmployeeController 中更改 Index 行为方法
更改 EmployeeController 中的 Index 行为方法如下:
public ActionResult Index() { …… …… …… employeeListViewModel.Employees = empViewModels; //employeeListViewModel.UserName = "Admin";-->Remove this line -->Change1 return View("Index", employeeListViewModel);//-->Change View Name -->Change 2}
现在执行的 URL 将会为:「…/Employee/Index」。
第一步:创建 Action 方法
在 EmployeeController 中创建一个 Action 方法,命名为「AddNew」,如下:
public ActionResult AddNew() { return View("CreateEmployee");}
第二步:创建 View
在文件夹 View/Employee 下创建一个 View,命名为「CreateEmployee」。代码如下:
@{ Layout = null;}<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>CreateEmployee</title> </head> <body> <div> <form action="/Employee/SaveEmployee" method="post"> First Name: <input type="text" id="TxtFName" name="FirstName" value="" /><br /> Last Name: <input type="text" id="TxtLName" name="LastName" value="" /><br /> Salary: <input type="text" id="TxtSalary" name="Salary" value="" /><br /> <input type="submit" name="BtnSave" value="Save Employee" /> <input type="button" name="BtnReset" value="Reset" /> </form> </div> </body></html>
第三步:在 Index 视图中创建一个链接
打开 Index.cshtml,然后增加一个超链接指向 AddNew 行为的URL。
<ahref="/Employee/AddNew">Add New</a>
第四步:执行并测试应用
按下 F5 并执行应用。
Form 标签的目的是什么?
在第一天的系列学习中,我们已经明白了「Web 世界不会遵循事件驱动编程模型。它遵循的是请求响应模型。终端用户发出请求,然后服务器给出响应。」Form 标签是 HTML 中做出响应的其中一种方式。只要标签里的提交按钮被点击,一个请求就将发送给动作属性中指定的 URL 中。
Form 标签中的方法属性是什么?
它决定了请求的类型。请求也许是如下的其中一种:get、post、put 或者是 delete。
Get:当我们想获取什么数据时
Post:当我们想创建什么数据时
Put:当我们想更新什么数据时
Delete:当我们想删除什么数据时
运用 Form 标签和通过浏览器地址栏或者超链接来发出请求,有何区别?
当我们使用 Form 标签来发送请求时,所有输入控件中的值都会伴随着请求一起被处理。
Checkbox、Radio 按钮和 Dropdowns 控件中的值也会被发送吗?
答案是肯定的。所有输入控件(输入类型为 Text,Radio,Checkbox)以及 Dropdowns(表示的是被选中的元素)都会被发送。
输入的值如何发送给服务器?
当请求的类型是 Get、Put 或者 Delete 时,输入的值会以查询字符串参数的方式发送。
当请求的类型是 Post 时,输入的值会以 Post 数据发送。
输入控件中的 Name 属性的目的是什么