使用模型绑定和 Web 窗体检索和显示数据
本教程系列演示了将模型绑定与 ASP.NET Web Forms项目配合使用的基本方面。 模型绑定使数据交互比处理数据源对象(如 ObjectDataSource 或 SqlDataSource) ) (更直接。 本系列从介绍性材料开始,在后面的教程中将介绍更高级的概念。
模型绑定模式适用于任何数据访问技术。 在本教程中,你将使用 Entity Framework,但你可以使用你最熟悉的数据访问技术。 在数据绑定服务器控件(如 GridView、ListView、DetailsView 或 FormView 控件)中,指定要用于选择、更新、删除和创建数据的方法的名称。 在本教程中,你将为 SelectMethod 指定一个值。
在该方法中,提供用于检索数据的逻辑。 在下一教程中,你将为 UpdateMethod、DeleteMethod 和 InsertMethod 设置值。
可以使用 C# 或 Visual Basic 下载 完整的项目。 可下载的代码适用于 Visual Studio 2012 及更高版本。 它使用 Visual Studio 2012 模板,该模板与本教程中显示的 Visual Studio 2017 模板略有不同。
本教程在 Visual Studio 中运行应用程序。 还可以将应用程序部署到托管提供商,并通过 Internet 提供该应用程序。 Microsoft 在 中为最多 10 个网站提供免费 Web 托管
免费 Azure 试用帐户。 有关如何将 Visual Studio Web 项目部署到Azure 应用服务 Web 应用的信息,请参阅使用 Visual Studio ASP.NET Web 部署系列。 本教程还演示如何使用 Entity Framework Code First 迁移 将 SQL Server 数据库部署到 Azure SQL 数据库。本教程中使用的软件版本
- Microsoft Visual Studio 2017 或 Microsoft Visual Studio Community 2017
本教程还适用于 Visual Studio 2012 和 Visual Studio 2013,但在用户界面和项目模板方面存在一些差异。
生成目标
在本教程中,你将:
- 生成反映学生已注册课程的大学的数据对象
- 从对象生成数据库表
- 使用测试数据填充数据库
- 在 Web 窗体中显示数据
创建项目
在 Visual Studio 2017 中,创建名为 ContosoUniversityModelBinding的 ASP.NET Web 应用程序 (.NET Framework) 项目。
选择“确定” 。 此时将显示用于选择模板的对话框。
选择Web Forms模板。
如有必要,请将身份验证更改为 “个人用户帐户”。
选择“确定”以创建项目。
修改网站外观
进行一些更改以自定义网站外观。
打开 Site.Master 文件。
更改标题以显示 Contoso University ,而不是 “我的 ASP.NET 应用程序”。
<title><%: Page.Title %> - Contoso University</title>
将标题文本从 “应用程序名称” 更改为 “Contoso University”。
<div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" runat="server" href="~/">Contoso University</a> </div>
将导航标头链接更改为网站相应的链接。
删除“ 关于 ”和 “联系人” 的链接,并改为链接到要创建的 “学生 ”页面。
<ul class="nav navbar-nav"> <li><a runat="server" href="~/">Home</a></li> <li><a runat="server" href="~/Students">Students</a></li> </ul>
保存 Site.Master。
添加 Web 窗体以显示学生数据
在“解决方案资源管理器”中,右键单击项目,选择“添加”,然后选择“新建项”。
在“ 添加新项 ”对话框中,选择 包含母版页模板的 Web 窗体 ,并将其命名为 Students.aspx。
选择 添加 。
对于 Web 窗体的母版页,选择“ Site.Master”。
选择“确定” 。
添加数据模型
在 Models 文件夹中,添加名为 UniversityModels.cs 的类。
右键单击“ 模型”,选择“ 添加”,然后选择“ 新建项”。 此时会显示“添加新项”对话框。
在左侧导航菜单中,依次选择“ 代码”、“ 类”。
将课堂命名为 UniversityModels.cs ,然后选择“ 添加”。
在此文件中,定义
SchoolContext
、Student
、Enrollment
和Course
类,如下所示:using System; using System.Collections.Generic; using System.Data.Entity; using System.ComponentModel.DataAnnotations; namespace ContosoUniversityModelBinding.Models { public class SchoolContext : DbContext { public DbSet<Student> Students { get; set; } public DbSet<Enrollment> Enrollments { get; set; } public DbSet<Course> Courses { get; set; } } public class Student { [Key, Display(Name = "ID")] [ScaffoldColumn(false)] public int StudentID { get; set; } [Required, StringLength(40), Display(Name="Last Name")] public string LastName { get; set; } [Required, StringLength(20), Display(Name = "First Name")] public string FirstName { get; set; } [EnumDataType(typeof(AcademicYear)), Display(Name = "Academic Year")] public AcademicYear Year { get; set; } public virtual ICollection<Enrollment> Enrollments { get; set; } } public class Enrollment { [Key] public int EnrollmentID { get; set; } public int CourseID { get; set; } public int StudentID { get; set; } public decimal? Grade { get; set; } public virtual Course Course { get; set; } public virtual Student Student { get; set; } } public class Course { [Key] public int CourseID { get; set; } public string Title { get; set; } public int Credits { get; set; } public virtual ICollection<Enrollment> Enrollments { get; set; } } public enum AcademicYear { Freshman, Sophomore, Junior, Senior } }
类
SchoolContext
派生自DbContext
,后者管理数据库连接和数据更改。Student
在 类中,请注意应用于 、LastName
和Year
属性的属性FirstName
。 本教程使用这些属性进行数据验证。 为了简化代码,只有这些属性使用数据验证属性进行标记。 在实际项目中,需要验证的所有属性都应用验证属性。保存 UniversityModels.cs。
基于类设置数据库
本教程使用 Code First 迁移 创建对象和数据库表。 这些表存储有关学生及其课程的信息。
选择“工具”>“NuGet 包管理器”>“包管理器控制台”。
在 包管理器控制台中,运行以下命令:
enable-migrations -ContextTypeName ContosoUniversityModelBinding.Models.SchoolContext
如果命令成功完成,将显示一条消息,指出已启用迁移。
请注意,已创建名为 Configuration.cs 的文件。 类
Configuration
具有一个Seed
方法,该方法可以使用测试数据预填充数据库表。
预填充数据库
打开 Configuration.cs。
将以下代码添加到
Seed
方法中。 此外,为ContosoUniversityModelBinding. Models
命名空间添加using
语句。namespace ContosoUniversityModelBinding.Migrations { using System; using System.Data.Entity; using System.Data.Entity.Migrations; using System.Linq; using ContosoUniversityModelBinding.Models; internal sealed class Configuration : DbMigrationsConfiguration<SchoolContext> { public Configuration() { AutomaticMigrationsEnabled = false; } protected override void Seed(SchoolContext context) { context.Students.AddOrUpdate( new Student { FirstName = "Carson", LastName = "Alexander", Year = AcademicYear.Freshman }, new Student { FirstName = "Meredith", LastName = "Alonso", Year = AcademicYear.Freshman }, new Student { FirstName = "Arturo", LastName = "Anand", Year = AcademicYear.Sophomore }, new Student { FirstName = "Gytis", LastName = "Barzdukas", Year = AcademicYear.Sophomore }, new Student { FirstName = "Yan", LastName = "Li", Year = AcademicYear.Junior }, new Student { FirstName = "Peggy", LastName = "Justice", Year = AcademicYear.Junior }, new Student { FirstName = "Laura", LastName = "Norman", Year = AcademicYear.Senior }, new Student { FirstName = "Nino", LastName = "Olivetto", Year = AcademicYear.Senior } ); context.SaveChanges(); context.Courses.AddOrUpdate( new Course { Title = "Chemistry", Credits = 3 }, new Course { Title = "Microeconomics", Credits = 3 }, new Course { Title = "Macroeconomics", Credits = 3 }, new Course { Title = "Calculus", Credits = 4 }, new Course { Title = "Trigonometry", Credits = 4 }, new Course { Title = "Composition", Credits = 3 }, new Course { Title = "Literature", Credits = 4 } ); context.SaveChanges(); context.Enrollments.AddOrUpdate( new Enrollment { StudentID = 1, CourseID = 1, Grade = 1 }, new Enrollment { StudentID = 1, CourseID = 2, Grade = 3 }, new Enrollment { StudentID = 1, CourseID = 3, Grade = 1 }, new Enrollment { StudentID = 2, CourseID = 4, Grade = 2 }, new Enrollment { StudentID = 2, CourseID = 5, Grade = 4 }, new Enrollment { StudentID = 2, CourseID = 6, Grade = 4 }, new Enrollment { StudentID = 3, CourseID = 1 }, new Enrollment { StudentID = 4, CourseID = 1 }, new Enrollment { StudentID = 4, CourseID = 2, Grade = 4 }, new Enrollment { StudentID = 5, CourseID = 3, Grade = 3 }, new Enrollment { StudentID = 6, CourseID = 4 }, new Enrollment { StudentID = 7, CourseID = 5, Grade = 2 } ); context.SaveChanges(); } } }
保存 Configuration.cs。
在包管理器控制台中,运行 命令 add-migration initial。
运行 命令 update-database。
如果在运行此命令时收到异常,
StudentID
则 和CourseID
值可能与方法值不同Seed
。 打开这些数据库表,查找 和CourseID
的现有值StudentID
。 将这些值添加到代码中,以便对表进行种子设定Enrollments
。
添加 GridView 控件
使用填充的数据库数据,现在可以检索并显示该数据。
打开 Students.aspx。
MainContent
找到占位符。 在该占位符中,添加包含此代码的 GridView 控件。<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"> <asp:GridView runat="server" ID="studentsGrid" ItemType="ContosoUniversityModelBinding.Models.Student" DataKeyNames="StudentID" SelectMethod="studentsGrid_GetData" AutoGenerateColumns="false"> <Columns> <asp:DynamicField DataField="StudentID" /> <asp:DynamicField DataField="LastName" /> <asp:DynamicField DataField="FirstName" /> <asp:DynamicField DataField="Year" /> <asp:TemplateField HeaderText="Total Credits"> <ItemTemplate> <asp:Label Text="<%# Item.Enrollments.Sum(en => en.Course.Credits) %>" runat="server" /> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView> </asp:Content>
注意事项:
请注意 GridView 元素中为
SelectMethod
属性设置的值。 此值指定用于检索在下一步中创建的 GridView 数据的方法。属性
ItemType
设置为Student
前面创建的类。 此设置允许引用标记中的类属性。 例如,Student
类具有名为 的Enrollments
集合。 可以使用Item.Enrollments
检索该集合,然后使用 LINQ 语法 检索每个学生的注册学分总和。
保存 Students.aspx。
添加代码以检索数据
在 Students.aspx 代码隐藏文件中,添加为 SelectMethod
值指定的 方法。
打开 Students.aspx.cs。
为
ContosoUniversityModelBinding. Models
和System.Data.Entity
命名空间添加using
语句。using ContosoUniversityModelBinding.Models; using System.Data.Entity;
添加为
SelectMethod
指定的方法:public IQueryable<Student> studentsGrid_GetData() { SchoolContext db = new SchoolContext(); var query = db.Students.Include(s => s.Enrollments.Select(e => e.Course)); return query; }
子
Include
句可提高查询性能,但不是必需的。Include
如果没有 子句,则使用延迟加载检索数据,这涉及到每次检索相关数据时都会向数据库发送单独的查询。Include
使用 子句,使用预先加载检索数据,这意味着单个数据库查询检索所有相关数据。 如果未使用相关数据,则预先加载效率较低,因为检索的数据更多。 但是,在这种情况下,预先加载可提供最佳性能,因为每个记录都显示相关数据。有关加载相关数据时的性能注意事项的详细信息,请参阅 ASP.NET MVC 应用程序中使用实体框架读取相关数据一文中的延迟、预先和显式加载相关数据部分。
默认情况下,数据按标记为键的属性的值进行排序。 可以添加 子
OrderBy
句以指定不同的排序值。 在此示例中,默认StudentID
属性用于排序。 在 排序、分页和筛选数据 一文中,用户可选择要排序的列。保存 Students.aspx.cs。
运行应用程序
(F5) 运行 Web 应用程序,然后导航到“ 学生 ”页,其中显示以下内容:
自动生成模型绑定方法
完成本教程系列时,只需将教程中的代码复制到项目中即可。 但是,此方法的一个缺点是,你可能不知道 Visual Studio 提供的用于自动生成模型绑定方法代码的功能。 在处理自己的项目时,自动生成代码可以节省时间,并帮助你了解如何实现操作。 本部分介绍自动生成代码功能。 本部分仅提供信息,不包含需要在项目中实现的任何代码。
在标记代码中 SelectMethod
为 、 UpdateMethod
、 InsertMethod
或 DeleteMethod
属性设置值时,可以选择 “创建新方法” 选项。
Visual Studio 不仅在代码隐藏中创建具有适当签名的方法,而且还生成实现代码来执行操作。 如果在使用自动生成代码功能之前首先设置 ItemType
属性,则生成的代码将使用该类型执行操作。 例如,设置 UpdateMethod
属性时,会自动生成以下代码:
// The id parameter name should match the DataKeyNames value set on the control
public void studentsGrid_UpdateItem(int id)
{
ContosoUniversityModelBinding.Models.Student item = null;
// Load the item here, e.g. item = MyDataLayer.Find(id);
if (item == null)
{
// The item wasn't found
ModelState.AddModelError("", String.Format("Item with id {0} was not found", id));
return;
}
TryUpdateModel(item);
if (ModelState.IsValid)
{
// Save changes here, e.g. MyDataLayer.SaveChanges();
}
}
同样,无需将此代码添加到项目中。 在下一教程中,你将实现更新、删除和添加新数据的方法。
总结
在本教程中,你创建了数据模型类,并从这些类生成了一个数据库。 用测试数据填充了数据库表。 你使用模型绑定从数据库中检索数据,然后在 GridView 中显示数据。
在本系列的下一 个教程 中,你将启用更新、删除和创建数据。