假设我正在从几个相关表格生成视图模型。以这种方式查询有什么优点/差异/缺点:
var enrollment = db.enrollment
.Include(d => d.cohort.OldCourses.OldCourseSections.Select(f => f.OldCoursePages))
.Include(d => d.OldProgress)
.FirstOrDefault(b => b.UserID == currentuser && b.cohort.OldCourses.Titleabbrev == courseabbrev);
var viewModel = new OldSectionViewModel();
viewModel.OldCourseTitle = enrollment.cohort.OldCourses.OldCourseTitle;
viewModel.OldCourseSec_title = enrollment.cohort.OldCourses.OldCourseSections.FirstOrDefault(f => f.OldCourseSec_abbrev == secabbrev).OldCourseSec_title;
viewModel.Meta = enrollment.cohort.OldCourses.Meta;
viewModel.Titleabbrev = enrollment.cohort.OldCourses.Titleabbrev;
viewModel.OldCourseSec_abbrev = enrollment.cohort.OldCourses.OldCourseSections.FirstOrDefault(f => f.OldCourseSec_abbrev == secabbrev).OldCourseSec_abbrev;
viewModel.progress = currentprogress;
viewModel.pages = enrollment.cohort.OldCourses.OldCourseSections.FirstOrDefault(f => f.OldCourseSec_abbrev == secabbrev).OldCourse_Page_Total;
viewModel.EnrollmentID = enrollment.EnrollmentID;
viewModel.OldCourseSectionID = enrollment.cohort.OldCourses.OldCourseSections.FirstOrDefault(f => f.OldCourseSec_abbrev == secabbrev).OldCourseSectionID;
viewModel.OldCoursePage_title = enrollment.cohort.OldCourses.OldCourseSections.FirstOrDefault(f => f.OldCourseSec_abbrev == secabbrev).OldCoursePages.FirstOrDefault(g => g.OldCoursePage_Order ==
currentprogress).OldCoursePage_title;
viewModel.OldCoursePage_HTML = enrollment.cohort.OldCourses.OldCourseSections.FirstOrDefault(f => f.OldCourseSec_abbrev == secabbrev).OldCoursePages.FirstOrDefault(g => g.OldCoursePage_Order ==
currentprogress).OldCoursePage_HTML;
viewModel.OldCoursePage_Order = enrollment.cohort.OldCourses.OldCourseSections.FirstOrDefault(f => f.OldCourseSec_abbrev == secabbrev).OldCoursePages.FirstOrDefault(g => g.OldCoursePage_Order ==
currentprogress).OldCoursePage_Order;
或者这样:
var viewModel = db.enrollment
.Where(b => b.UserID == currentuser && b.cohort.OldCourses.Titleabbrev == courseabbrev)
.Select(x => new OldSectionViewModel
{
OldCourseTitle = x.cohort.OldCourses.OldCourseTitle,
OldCourseSec_title = x.cohort.OldCourses.OldCourseSections.FirstOrDefault(f => f.OldCourseSec_abbrev == secabbrev).OldCourseSec_title,
Meta = x.cohort.OldCourses.Meta,
Titleabbrev = x.cohort.OldCourses.Titleabbrev,
OldCourseSec_abbrev = x.cohort.OldCourses.OldCourseSections.FirstOrDefault(f => f.OldCourseSec_abbrev == secabbrev).OldCourseSec_abbrev,
progress = currentprogress,
pages = x.cohort.OldCourses.OldCourseSections.FirstOrDefault(f => f.OldCourseSec_abbrev == secabbrev).OldCourse_Page_Total,
EnrollmentID = x.EnrollmentID,
OldCourseSectionID = x.cohort.OldCourses.OldCourseSections.FirstOrDefault(f => f.OldCourseSec_abbrev == secabbrev).OldCourseSectionID,
OldCoursePage_title = x.cohort.OldCourses.OldCourseSections.FirstOrDefault(f => f.OldCourseSec_abbrev == secabbrev).OldCoursePages.FirstOrDefault(g => g.OldCoursePage_Order ==
currentprogress).OldCoursePage_title,
OldCoursePage_HTML = x.cohort.OldCourses.OldCourseSections.FirstOrDefault(f => f.OldCourseSec_abbrev == secabbrev).OldCoursePages.FirstOrDefault(g => g.OldCoursePage_Order ==
currentprogress).OldCoursePage_HTML,
OldCoursePage_Order = x.cohort.OldCourses.OldCourseSections.FirstOrDefault(f => f.OldCourseSec_abbrev == secabbrev).OldCoursePages.FirstOrDefault(g => g.OldCoursePage_Order ==
currentprogress).OldCoursePage_Order,
}).Single();
假设'currentprogress'是其他地方设置的整数。在我看来,第二个查询将稍微更有效,因为我加载我需要的特定字段,而第一个查询我加载整个表。然而,我对这些事情的理解是非常基本的,我很想知道哪些更有效,以及为什么真正知道他们在谈论什么的人呢?
这两个查询是否都符合急切加载的要求?
答案 0 :(得分:1)
简单地说,在第一种方法中,您将所有相关表包含在一个查询中。在第二种方法中,您将生成N + 1个查询。
虽然一般来说你应该避免N + 1查询情况,但它也依赖很多来解决数据发生的问题。一次查询这么多相关表格会减少大量数据,而这些连接的性质意味着你将要删除所有相关项目。例如,如果您实际上只需要像每个相关项目那样,那么通过执行一个大查询,您将返回大量您永远不会使用的数据。
执行N + 1查询可能意味着向您的服务器发送大量查询,但“很多”的定义是可变的。如果它最终成为10-20个相对较小的查询,并且你有一个拥有大量资源的良好数据库服务器实例,它可能没那么重要,而你最好,那么,只选择你真正需要的数据
此外,您可以使用内存缓存,这样您可能只需要每小时或最多运行一次这些查询。你只需要研究两种方案中发生的事情,并确定哪种方案最有效/最有意义。
答案 1 :(得分:1)
var viewModel = db.enrollment
.Where(b => b.UserID == currentuser && b.cohort.OldCourses.Titleabbrev == courseabbrev).ToList()
.Select(x =>
{
var oldCourseSection = x.cohort.OldCourses.OldCourseSections.FirstOrDefault(f => f.OldCourseSec_abbrev == secabbrev);
var oldCourseSectionPage = oldCourseSection.OldCoursePages.FirstOrDefault(g => g.OldCoursePage_Order == currentprogress);
return new OldSectionViewModel()
{
OldCourseTitle = x.cohort.OldCourses.OldCourseTitle,
OldCourseSec_title = oldCourseSection.OldCourseSec_title,
Meta = x.cohort.OldCourses.Meta,
Titleabbrev = x.cohort.OldCourses.Titleabbrev,
OldCourseSec_abbrev = oldCourseSection.OldCourseSec_abbrev,
progress = currentprogress,
pages = oldCourseSection.OldCourse_Page_Total,
EnrollmentID = x.EnrollmentID,
OldCourseSectionID = oldCourseSection.OldCourseSectionID,
OldCoursePage_title = oldCourseSectionPage.OldCoursePage_title,
OldCoursePage_HTML = oldCourseSectionPage.OldCoursePage_HTML,
OldCoursePage_Order = oldCourseSectionPage.OldCoursePage_Order,
};}).Single();
整点是在select中加载变量,你需要使用括号PLUS return关键字。这里有一个关于如何做到这一点的小例子。它允许您在返回匿名或类对象(两者都有效)之前运行代码
public class Item { public int Price { get; set; } = 0; public string Name { get; set; } = ""; }
static void Main(string[] args)
{
var Collection = new List<Item>();
var itemPrices = Collection.Select(item =>
{
var x = 10;
var y = item.Price;
return new { ItemName = item.Name, ItemPrice = x * y };
}).ToList();
itemPrices.ForEach(itemData =>
{
Console.WriteLine(itemData.ItemName + " " + itemData.ItemPrice.ToString());
});
}