实体框架导航属性加载

本文关键字:加载 属性 导航 框架 实体 | 更新日期: 2023-09-27 18:19:49

我使用的是带有Fluent API的EF。

所以我有两个类,有一对多关系

public class Room {
    //list of properties
    public List<Image> Images {get; set; }
}
public class Image {
    public Room Room {get; set; }
}

如果我第一次问房间

var rooms = ctx.Rooms.ToList();  

然后我要图像

var images = ctx.Images.ToList();

然后我浏览了房间集合,我发现每个房间都有她的图像列表,即使我在第一个查询中没有包含或投影图像。

这是怎么发生的?

编辑我知道要执行两个查询,这正是我想要的,因为现实世界中的第一个查询更复杂,并且加载了很多导航属性,所以我不希望图像参与连接。

我只是想了解上面的代码是如何工作的,我原以为我必须手动连接这两个列表,但不知何故,这是自动完成的。

实体框架导航属性加载

父实体下的所有子实体都是使用var images = ctx.Images.ToList();加载的子实体,它们本身就是;这是因为您使用代码优先约定或api定义了父级和子级之间的关系,所以它们被列在那里。

我想您已经禁用了延迟加载,所以您不应该担心性能,因为它们不会加载两次。这些是你自己直接加载的图像。


这里有一个简单的测试来获得这个概念。我有一个具有Parent实体和Child实体的上下文,它们之间定义了关系:

var db = new MyDbContext();
db.Configuration.LazyLoadingEnabled = false;
var parents = db.Parents.ToList();
//Shows False, So childs are not loaded.
Console.WriteLine(parents.Any(x => x.Childs.Count() > 0).ToString());
var childs = db.Childs.ToList();
//Shows True, We didn't loads Parents again, and EF only relates them.
Console.WriteLine(parents.Any(x => x.Childs.Count() > 0).ToString());

我将尝试用一些测试来解释这个场景。。。

public class Room {
    public int Id {get; set;}
    public List<Image> Images {get; set; }
}
public class Image {
    public Room Room {get; set; }
}

我希望所有的测试都能通过…

[TestMethod]
public void NoLazyLoadingAndNoEagerLoading()
{
  var _db = new dbContext();
  var rooms = _db.Rooms.ToList();
  //All images will be null
  Assert.IsFalse(rooms.Any(x => x.Images != null));
  _db.Dispose();
}
[TestMethod]
public void NoLazyLoadingAndNoEagerLoading()
{
  var _db = new dbContext();
  var rooms = _db.Rooms.Include(x => x.Images).ToList();   
  //We have eager loaded them in the first query.
  Assert.IsTrue(rooms.Any(x => x.Images != null));
  _db.Dispose();
}

同样带有Lazy Loading和以下型号调整

public class Room {
    public int Id {get; set;}
    public virtual List<Image> Images {get; set; }
}
public void NoLazyLoadingAndNoEagerLoading()
{
  var _db = new dbContext();
  var rooms = _db.Rooms.ToList();
  //Now lazy loading should kick in,
  //Entity framework will make more calls to the db and return Images
  Assert.IsFalse(rooms.Any(x => x.Images != null));
  _db.Dispose();
}