EF6:将 DataGridView 的 DataSource 设置为 EF-Entity 也会导致加载其子项。为什么?

EF6: Setting DataGridView's DataSource to an EF-Entity results in loading its children as well. Why?

我正在努力使它尽可能简短:

我有一个包含一些表的简单数据库: 艺术家、专辑、歌曲。

  1. 艺术家可能有多张专辑。专辑可能是由多位艺术家(多对多)创建的。
  2. 一个专辑可以有多首歌曲,但一首歌曲仅限于一张专辑(一对多)。

EntityFramework把这些表放到类就好了。现在,我将 DbContext 实例绑定到 Windows Forms C# 项目中的 DataGridView:

DBEntities db = new DBEntities();
db.Artists.Include(a => a.Albums).Load(); // include children albums as well
artistBindingSource.DataSource = db.Artists.Local.ToBindingList();

DataGridView 实例正确显示内容。我可以保存修改之类的。

如果用户单击 DataGridView 中的单元格(带有艺术家姓名),我将通过将第二个 DataGridView(带有 albumBindingSource)分配给艺术家的专辑集合来加载相关专辑:

Artist a = (Artist)row.DataBoundItem; // row contains selected grid row
if (a != null)
{
    albumBindingSource.DataSource = a.Albums;
}

这也可以,但是在调试 SQL 语句时我发现了一些奇怪的东西: 将第二个 DataGridView 的数据源分配给 a.albums(即所选实例的专辑)时,Entity Framework 还会在多个 SELECT 语句(每首歌曲一个)中延迟加载专辑的歌曲。

问题 1: 为什么还要加载相册的子项?我从来没有告诉它这样做。


但是:如果我将以下代码添加到预加载实体的行中,延迟加载就会消失:

db.Artists.Include(c => c.Albums.Select(b => b.Songs)).Load();

问题 2: 我真的需要预加载所有的子孙子代以防止延迟加载吗?我从来不希望孙子们出现在我的 Windows 表格中。

问题三:(见Q.2)为什么是"include"然后是"select"?我觉得像...

db.Artists.Include(c => c.Albums.Include(d => d.Songs)).Load();

...会更直观。

无论如何:感谢您在这里帮助我!

正在加载实体可能是因为 LazyLoading 已打开。您可以通过 db.Configuration.LazyLoadingEnabled = false; 关闭 LazyLoading,无需加载所有内容。此外,还有两个 Include 方法(不包括 overloads)。一个是DbQuery<TEntity>的方法,DbSet<TEntity>继承了它,所以你可以看到Include方法为你的集合,另一个是QuerableExtensions class中的方法,这是扩展方法IQuerable<T>,在 System.Data.Entity 命名空间中。所以它是为 IQuerable 编写的,您使用 Select 方法指定子集合。