【问题标题】:Eager loading, Entity Framework急切加载,实体框架
【发布时间】:2021-03-17 04:33:24
【问题描述】:

我有一个专辑类和两个与之相关的类,流派和艺术家。我使用即时加载来加载专辑对象和链接的实体:

var albums = db.Albums.Include(a => a.Artist).Include(a => a.Genre);

加载后,我尝试从数据集中的相册对象访问链接实体的属性,但导航属性为空

Album album = db.Albums.Find(id);
var name = album.Genre.Name;

name 为空。

我的问题是,在预先加载之后,专辑数据集中加载的对象是否包含对链接实体“艺术家”和“流派”的引用?

我不想激活延迟加载。

谢谢

【问题讨论】:

  • db.Albums.Find() 执行单独的查询。使用Album album = albums.FirstOrDefault(a => a.Id == id);。然后,您可以访问album.Genre
  • 这是db 的同一个实例吗?一旦它们在更改跟踪器中,它们应该被链接。
  • @JeremyLakeman 仅当 albums 查询实际加载到内存中时(这里不是这种情况)。调用 albums.ToList()albums.Load() 应该可以解决问题。
  • 对.. 错过了专辑仍然是 IQueryable。

标签: c# asp.net-mvc entity-framework eager-loading


【解决方案1】:

当延迟加载启用时,导航属性(链接实体或实体集合)会在您首次访问时自动加载。这就是为什么 album.Genre 可以正常工作,只要 DbContext 还没有被释放或者之前已经访问过(某个专辑的)Genre 属性。

当延迟加载被禁用时,您就没有这种灵活性了。您需要急切(或明确)加载链接的实体。使用Include() (Eagerly Loading),您将获得正确的开始。然而,由于albums 尚未具体化(未加载到内存中),尝试通过执行不同 查询(这是db.Albums.Find() 所做的)来访问Genre 属性将失败。

这里有两个选择...

具体化查询:

var albums = db.Albums.Include(a => a.Artist).Include(a => a.Genre).ToList();
Album album = db.Albums.Find(id);
// Works because all `Album.Genre` **of all `Album` records** is loaded into the EF cache.
var name = album.Genre.Name;

使用包含链接实体的相同查询查找目标专辑:

var albums = db.Albums.Include(a => a.Artist).Include(a => a.Genre)
// This will force EF to load the "included" entities for this one specific record.
Album album = albums.FirstOrDefault(a => a.Id == id);
var name = album.Genre.Name;

【讨论】:

    猜你喜欢
    • 2011-04-09
    • 2012-02-07
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    • 2011-05-03
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多