实体框架导航属性加载

时间:2015-10-29 12:52:28

标签: c# entity-framework

我正在使用EF和Fluent API。

所以我有两个有一对多关系的课程

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();

然后我探索房间Collection,我看到每个房间都有她的图像列表,即使我在第一次查询中没有包含也没有投影图像。

这是怎么发生的?

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

我只是想了解上面的代码是如何工作的,我预计我必须手动加入这两个列表,但不知怎的,这是自动完成的。

2 个答案:

答案 0 :(得分:2)

父实体下的所有子项,是您使用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());

答案 1 :(得分:0)

我会尝试用一些测试来解释这个场景......

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();

}

同时使用延迟加载和以下模型调整

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();
}