在有主外键关系的表中,根据数据库表结构生成实体类时,会生成如下内容:
在新闻类别表中会生成virtual类型的属性,这是导航属性。(主表中有子表的集合)
在新闻表中会生成virtual类型的属性,这是引用属性。(子表中有主表的实例)
实例1:
{
using (NewsDbContext dbContext = new NewsDbContext())
{
//打印sql信息
dbContext.Database.Log += c => Console.WriteLine($"sql:{c}");
var list = dbContext.Set<NewsClassify>();
//开始查询主表信息
foreach (var nc in list)
{
Console.WriteLine(nc.Name);
//开始查询子表信息
foreach (var n in nc.News)
{
Console.WriteLine(n.Title);
}
}
}
}
查询结果:
先查询了主表数据(新闻类别表)。
然后再分别查询子表数据(新闻表)。
总结:导航属性的延迟查询,子表在遍历时才去查询,主子表分别查询。
实例2:
{
using (NewsDbContext dbContext = new NewsDbContext())
{
//打印sql信息
dbContext.Database.Log += c => Console.WriteLine($"sql:{c}");
dbContext.Configuration.LazyLoadingEnabled = false;//关闭延迟查询
var list = dbContext.Set<NewsClassify>();
foreach (var nc in list)
{
Console.WriteLine(nc.Name);
foreach (var n in nc.News)
{
Console.WriteLine(n.Title);
}
}
}
}
查询结果:
只会查询出主表数据(新闻类别表)。
总结:dbContext.Configuration.LazyLoadingEnabled = false; 关闭延迟查询,子表(新闻表)数据不会被查询出来。只会查询出主表(新闻类别表)数据。
实例3:
{
using (NewsDbContext dbContext = new NewsDbContext())
{
//打印sql信息
dbContext.Database.Log += c => Console.WriteLine($"sql:{c}");
dbContext.Configuration.LazyLoadingEnabled = false;//关闭延迟查询
var list = dbContext.Set<NewsClassify>();
foreach (var nc in list)
{
Console.WriteLine(nc.Name);
//显式查询子表数据
dbContext.Entry(nc).Collection(c => c.News).Load();
//dbContext.Entry(nc).Reference(c => c.News).Load();
foreach (var n in nc.News)
{
Console.WriteLine(n.Title);
}
}
}
}
查询结果:
和实例1相同,先查询主表(新闻类别表)再查询子表(新闻表)数据。
总结:dbContext.Configuration.LazyLoadingEnabled = false; 关闭延迟查询,子表(新闻表)数据不会被查询出来。只会查询出主表(新闻类别表)数据。
但是想要查询子表数据,也是可以的,需要显式查询子表数据。
实例4:
{
using (NewsDbContext dbContext = new NewsDbContext())
{
//打印sql信息
dbContext.Database.Log += c => Console.WriteLine($"sql:{c}");
var list = dbContext.Set<NewsClassify>().Include("News");
foreach (var nc in list)
{
Console.WriteLine(nc.Name);
foreach (var n in nc.News)
{
Console.WriteLine(n.Title);
}
}
}
}
查询结果:
一次性将主子表数据查询出来。
总结:Include的方式称为预加载,主子表数据在一个sql中同时查询出来。
以上四种查询,各有不同,根据需要使用不同方式。