【EF6学习笔记】(七)读取关联数据
本篇参考原文链接:Reading Related Data
本章主要讲述加载显示关联数据;
数据加载分为以下三种
Lazy loading
这种加载方式在于需要用到这个导航属性数据的时候,才会去数据库取数据,如下图,循环中,每一次都去数据库取一次数据:
Eager loading
这种加载方式则是先定义好哪个导航属性数据需要一起加载(通过是.Inclue),然后在加载主数据的时候,一并把导航数据全部加载,如下图:
Explicit loading
这种加载就是需要明确用代码来定义去数据库取数据(通过Collection.Load()或者Reference.Load()),一般是用在Lazy Loading 被关闭的情况下;如:
性能考虑
显而易见,Lazy Loading和Eager Loading 各有优势劣势;
Lazy Loading可以在需要的时候才取数据,那么不需要的时候就节约了资源;但需要的时候也对数据库产生了很大压力;
Eager Loading可以在需要的时候一次性取到全部数据,对于数据库压力来说会好很多;
所以,根据自己需要选择哪一种咯。。。
序列化之前关闭Lazy Loading
如果要序列化一个实体,会出现导航属性一层一层展下去,出现循环等等问题,所以在WEB API或者特定应用场景下需要序列化实例的时候,需要做些特殊处理;
准备深入学习此部分;计划后续再补充这部分;
新建Course页面来显示包含Department
这次偷偷懒,直接用带View 使用EF的控制器模板来创建Course控制器:
在控制器里,Index Action 已经直接把Department导航属性加载了:
// GET: Courses
public ActionResult Index()
{
var courses = db.Courses.Include(c => c.Department);
return View(courses.ToList());
}
然后把Courses/Index 试图改为:
(注意:个人偷懒,创建控制器的时候,Course控制器被自动创建为CoursesController, 所以要手动改下Home/Index里对应Course的Action Link参数)
(另外:要Department标题显示Department 而不是Name ,则需要到Department模型里把Name这个属性加上 [Display(Name ="Department")]
@model IEnumerable<EFTest.Models.Course> @{
ViewBag.Title = "Courses";
} <h2>Courses</h2> <p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.CourseID)
</th>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Credits)
</th>
<th>
@Html.DisplayNameFor(model => model.Department.Name)
</th>
<th></th>
</tr> @foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.CourseID)
</td>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Credits)
</td>
<td>
@Html.DisplayFor(modelItem => item.Department.Name)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.CourseID }) |
@Html.ActionLink("Details", "Details", new { id=item.CourseID }) |
@Html.ActionLink("Delete", "Delete", new { id=item.CourseID })
</td>
</tr>
} </table>
新建Instructors列表显示页面
准备建一个可以分多级显示的页面,上部显示Instructor列表,点击选择后,中部显示对应的Enrollment列表,再点击选择后,显示Enrollment对应的学生和成绩列表;
先准备一个显示用的模型:InstructorIndexData
在项目下新建ViewModels文件夹,然后增加一个显示模型:
using EFTest.Models;
using System.Collections.Generic; namespace EFTest.ViewModels
{
public class InstructorIndexData
{
public IEnumerable<Instructor> Instructors { get; set; }
public IEnumerable<Course> Courses { get; set; }
public IEnumerable<Enrollment> Enrollments { get; set; } }
}
然后新增 Instructor 控制器:
(注意把控制器名字改为 InstructorController)
在控制器里增加显示用模型文件夹的申明:
using EFTest.ViewModels;
把原先的Index Action 改为如下:
public ActionResult Index(int? id, int? courseID)
{
var viewModel = new InstructorIndexData();
viewModel.Instructors = db.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.Courses.Select(c => c.Department))
.OrderBy(i => i.LastName); if (id != null)
{
ViewBag.InstructorID = id.Value;
viewModel.Courses = viewModel.Instructors.Where(
i => i.ID == id.Value).Single().Courses;
} if (courseID != null)
{
ViewBag.CourseID = courseID.Value;
viewModel.Enrollments = viewModel.Courses.Where(
x => x.CourseID == courseID).Single().Enrollments;
//var selectedCourse = viewModel.Courses.Where(x => x.CourseID == courseID).Single();
//db.Entry(selectedCourse).Collection(x => x.Enrollments).Load();
//foreach (Enrollment enrollment in selectedCourse.Enrollments)
//{
// db.Entry(enrollment).Reference(x => x.Student).Load();
//}
//viewModel.Enrollments = selectedCourse.Enrollments;
}
return View(viewModel);
}
VIEW修改为:
(分为3部分显示,上部列表显示Instructors ,并增加一个Select的Link指向Index并带回ID值;中间部分显示选中的Instructor的Course列表,并也增加一个Select的LINK,
指向Index 并带回Instructors ID以及CourseID, 最下部分则为选中的Course的Enrollments列表;)
@model EFTest.ViewModels.InstructorIndexData @{
ViewBag.Title = "Instructors";
} <h2>Instructors</h2> <p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>Last Name</th>
<th>First Name</th>
<th>Hire Date</th>
<th>Office</th>
<th></th>
</tr> @foreach (var item in Model.Instructors)
{
string selectedRow = "";
if (item.ID == ViewBag.InstructorID)
{
selectedRow = "success";
}
<tr class="@selectedRow">
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.HireDate)
</td>
<td>
@if (item.OfficeAssignment != null)
{
@item.OfficeAssignment.Location
}
</td>
<td>
@Html.ActionLink("Select", "Index", new { id = item.ID }) |
@Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
@Html.ActionLink("Details", "Details", new { id = item.ID }) |
@Html.ActionLink("Delete", "Delete", new { id = item.ID })
</td>
</tr>
} </table>
@if (Model.Courses != null)
{
<h3>Courses Taught by Selected Instructor</h3>
<table class="table">
<tr>
<th></th>
<th>Number</th>
<th>Title</th>
<th>Department</th>
</tr> @foreach (var item in Model.Courses)
{
string selectedRow = "";
if (item.CourseID == ViewBag.CourseID)
{
selectedRow = "success";
}
<tr class="@selectedRow">
<td>
@Html.ActionLink("Select", "Index", new { courseID = item.CourseID })
</td>
<td>
@item.CourseID
</td>
<td>
@item.Title
</td>
<td>
@item.Department.Name
</td>
</tr>
} </table>
} @if (Model.Enrollments != null)
{
<h3>
Students Enrolled in Selected Course
</h3>
<table class="table">
<tr>
<th>Name</th>
<th>Grade</th>
</tr>
@foreach (var item in Model.Enrollments)
{
<tr>
<td>
@item.Student.FullName
</td>
<td>
@Html.DisplayFor(modelItem => item.Grade)
</td>
</tr>
}
</table>
}
扩展学习
原文中是采用直接刷新全部页面来显示,至于在实际项目中,有时候为了好的操作体验,采用Ajax来显示;
下面自己学习使用Ajax来进行点选Instructor后显示Course部分视图;
先做些准备工作:
通过NuGet 把项目中原 jQuery升级到最新;然后安装 Microsoft.jQuery.Unobtrusive.Ajax
(Microsoft.jQuery.Unobtrusive.Ajax是包含了 jQuery.Unobtrusive.Ajax 的微软包)
再把Home/Index对应的View加一行:
@{
ViewBag.Title = "Hello EF6";
}
<h2>Hello EF6</h2>
<div>
<ul>
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Students", "Index", "Student")</li>
<li>@Html.ActionLink("Courses", "Index", "Courses")</li>
<li>@Html.ActionLink("Instructors", "Index", "Instructor")</li>
<li>@Html.ActionLink("Ajax_Instructors", "Index", "Instructors")</li>
<li>@Html.ActionLink("Departments", "Index", "Department")</li>
</ul>
</div>
在Shared/_Layout.cshtml 这个模板View中加入应用:(这个办法是笨办法,还有一种是高级压缩的js引用办法,先用笨办法)
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
<link href="~/Content/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="~/Scripts/modernizr-2.6.2.js"></script>
<script src="~/Scripts/jquery-3.1.1.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
</head>
新建一个InstructorsContorller :
这个控制器里的Index可以不用改,主要是改Instructors/Index对应的View: (增加一个Ajax的ActionLink) (以及一个准备放Course的结果的Div)
@model IEnumerable<EFTest.Models.Instructor>
@{
var ajaxOption = new AjaxOptions()
{
HttpMethod = "Get",UpdateTargetId = "CourseList"
};
} @{
ViewBag.Title = "Index";
} <h2>Index</h2> <p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.LastName)
</th>
<th>
@Html.DisplayNameFor(model => model.FirstMidName)
</th>
<th>
@Html.DisplayNameFor(model => model.HireDate)
</th>
<th>
@Html.DisplayNameFor(model => model.OfficeAssignment.Location)
</th>
<th></th>
</tr> @foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.HireDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.OfficeAssignment.Location)
</td>
<td>
@Ajax.ActionLink("Select","GetList","Courses", new { id = item.ID },ajaxOption)
@Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
@Html.ActionLink("Details", "Details", new { id=item.ID }) |
@Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
</table>
<div id="CourseList"></div>
最后为Courses控制器加一个GetList 这个Action: (返回的是一个GetList的部分视图)
public ActionResult GetList(int? id)
{
var courses = db.Instructors.Where(i => i.ID == id.Value).Single().Courses; return PartialView(courses.ToList());
}
为这个Action 新建视图: (勾选 Create as a partial view)
最后把这个View调整一下:
@model IEnumerable<EFTest.Models.Course> <h3>Courses Taught by Selected Instructor</h3>
<table class="table">
<tr>
<th>Number</th>
<th>
@Html.DisplayNameFor(model => model.Department.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Credits)
</th>
</tr> @foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.CourseID)
</td>
<td>
@Html.DisplayFor(modelItem => item.Department.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Credits)
</td>
</tr>
} </table>
最后效果:
主页面没有刷新,点击Instructor行的右侧Select的时候会在下面显示其关联的Course (没有设置加载时的动画,所以第一次点击查询,操作会显得有些生硬)
【EF6学习笔记】(七)读取关联数据的更多相关文章
- SpringMVC学习笔记七:SpringMVC的数据验证
SpringMVC支持JSR(Java Specification Requests, Java规范提案)303-Bean Validation数据验证规范,该规范的实现者很多,其中较常用的是 Hib ...
- EF学习笔记(七):读取关联数据
总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本篇参考原文链接:Reading Related Data 本章主要讲述加载显示关联数据: 数据加载分为以下三种 Lazy l ...
- 【EF6学习笔记】(八)更新关联数据
上一篇链接:EF学习笔记(七):读取关联数据 本篇原文链接:Updating Related Data 本篇主要考虑对于有关联的数据进行新增.删除.更新操作:比如Course .Instructor: ...
- 【EF6学习笔记】目录
[EF6学习笔记](一)Code First 方式生成数据库及初始化数据库实际操作 [EF6学习笔记](二)操练 CRUD 增删改查 [EF6学习笔记](三)排序.过滤查询及分页 [EF6学习笔记]( ...
- ASP.NET MVC5 及 EF6 学习笔记 - (目录整理)
个人从传统的CS应用开发(WPF)开始转向BS架构应用开发: 先是采用了最容易上手也是最容易搞不清楚状况的WebForm方式入手:到后面就直接抛弃了服务器控件的开发方式,转而采用 普通页面+Ajax+ ...
- EF6 学习笔记(一):Code First 方式生成数据库及初始化数据库实际操作
EF6 学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本篇参考原文地址: Creating an Entity Framework Data Model 说明:学习 ...
- Java IO学习笔记七:多路复用从单线程到多线程
作者:Grey 原文地址:Java IO学习笔记七:多路复用从单线程到多线程 在前面提到的多路复用的服务端代码中, 我们在处理读数据的同时,也处理了写事件: public void readHandl ...
- Contoso 大学 - 5 – 读取关联数据
原文 Contoso 大学 - 5 – 读取关联数据 By Tom Dykstra, Tom Dykstra is a Senior Programming Writer on Microsoft's ...
- (转)Qt Model/View 学习笔记 (七)——Delegate类
Qt Model/View 学习笔记 (七) Delegate 类 概念 与MVC模式不同,model/view结构没有用于与用户交互的完全独立的组件.一般来讲, view负责把数据展示 给用户,也 ...
- R学习笔记(4): 使用外部数据
来源于:R学习笔记(4): 使用外部数据 博客:心内求法 鉴于内存的非持久性和容量限制,一个有效的数据处理工具必须能够使用外部数据:能够从外部获取大量的数据,也能够将处理结果保存.R中提供了一系列的函 ...
随机推荐
- jQuery实现简单的五星好评
最近一直在认真的努力工作,今天工作完成得差不多了,比较轻松点,在工作中有遇到用jq实现五星好评功能,觉得简单又有用,所以空闲时间就想分享出来. css部分: <style> .u_star ...
- py3.0第四天 函数,生成器迭代器等
1.列表生成式,迭代器&生成器 孩子,我现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1,你怎么实现?你可能会想到2种方式 > ...
- 开发HR人事考试系统介绍
确定好需要开发的模块以及功能 一套人事考试系统主要模块: 1)组织管理:公司部门成员信息 2)人事管理:人事信息,离职管理,职务管理,岗位管理: 3)考勤管理:班次设置,停工放假,假日设置,刷卡记录, ...
- 第九周助教工作总结——NWNU李泓毅
1.助教博客链接: https://www.cnblogs.com/NWNU-LHY/ 2.作业要求博客链接: https://www.cnblogs.com/nwnu-daizh/p/1072688 ...
- homework1-201521410029
姓名:孙浩学号: 201521410029指导教师:高见 实验日期:2018年8月9日 1. 虚拟机安装与调试 安装好xp和kali虚拟机之后,查看这三者(包括主机)的i ...
- ionic 侧栏菜单用法
第一步: 引入js和css文件我这里是直接引入的cdn,ionic是基于angular的,bundle.min.js把常用angular的js已经压缩到一起,可以直接引入.bundle.min.js, ...
- Numpy1
列表转n维数组ndarray import numpy as np list=[1,2,3,4] n=np.array(list) random模块生成ndarray n1=np.random.ran ...
- scrum学习
一.关于Scrum 什么叫Scrum?Scrum是一种迭代式增量软件开发过程,通常用于敏捷软件开发.Scrum包括了一系列实践和预定义角色的过程骨架.Scrum中的主要角色包括同项目经理类似的Scru ...
- OOP随笔
父类为普通类: 内部可声明虚方法(virtual),并包含代码实现,子类中可以重写(override),也可以不重写直接用. 父类为(不可实例化的)抽象类: 可声明虚方法,同上. 也可以声明抽象方法( ...
- Breathe me
Help, I have done it again 帮帮我,我又做错了. I have been here many times before 哪怕这已经不是一两次了. Hurt myself ag ...