我正在运行测试场景来决定是否使用实体框架实现系统并遇到一个有趣的问题。我有一个存储在'Person'中的'PersonCollectable'对象的集合,每个'PersonCollectable'对象都是'Page';检索集合为我提供了我想要显示的所有'PersonCollectable'对象,但我也希望显示'Page'的名称。 这是否会导致对每个网页进行查询,从而对效果产生负面影响?
public class Person
{
public virtual ICollection<PersonCollectable> Collection { get; set; }
public int Id { get; set; }
public string Name { get; set; }
}
public class PersonCollectable
{
public int Id { get; set; }
public virtual Page Page { get; set; }
public int PageId { get; set; }
}
public class Page
{
public int Id { get; set; }
public string Name { get; set; }
}
这是检索信息并显示结果的测试代码。想象一下,该集合至少包含500个项目,因此每个Web请求可能会产生500个额外查询。开发机器可以处理这个,但我想知道这是否会破坏已发布的产品。
Person example = db.People.Single( s => s.Name == "Roel" );
foreach( PersonCollectable exampleCollectable in example.Collection ) {
Console.WriteLine( "{0} rated {1}", exampleCollectable.Page.Name, exampleCollectable.Rating );
}
请分享您的见解并帮助我回答这个问题,会导致对每个页面进行查询,从而对效果产生负面影响吗?谢谢。
答案 0 :(得分:4)
是的,它将导致500个查询,因为您加载导航属性的方式依赖于延迟加载(virtual
导航属性)。
如果要将整个对象图加载到数据库中,您必须在运行查询时使用Include
来告诉您:
Person example = db.People
.Include(s => s.Collection.Select(c => c.Page))
.Single(s => s.Name == "Roel");
(其余代码可以保持不变。)
在您的特定情况下,推荐的方法是使用投影,但这意味着您只需加载您需要的属性:
var example = db.People
.Where(s => s.Name == "Roel")
.Select(s => new
{
PersonName = s.Name,
CollectedData = s.Collection.Select(c => new
{
PageName = c.Page.Name,
Rating = c.Rating
})
})
.Single();
Console.WriteLine( "Person {0}:", example.PersonName);
foreach(var item in example.CollectedData)
{
Console.WriteLine( "{0} rated {1}", item.PageName, item.Rating );
}
您也可以使用Select(s => new MyViewType...)
等创建自己的名为“查看”类型,而不是使用匿名类型。