EF 4.1抽象集合加载问题

时间:2011-05-31 09:13:41

标签: c# entity-framework entity-framework-4.1

我首先遇到有关EF 4.1代码的问题。 我试图用一个简化的例子来演示。

假设我们有一个包含States集合的Country类。 州集合包含学校集合。 学校是一个抽象的课程。 它有ElementarySchool和HighSchool的专业。

HighSchool拥有DrivingCourses的收藏属性。 DrivingCourses和所有其他数据成功保存到数据库中。

我的问题是当我加载Country类时,DrivingCourses集合仍然为null。 (其他一切都还可以)

据我所知,问题是因为当ef加载并填充HighSchool类时,它不知道课程集合。

我无法添加此映射,因为使用流畅的api静态反射,我只能映射(抽象)学校类的属性。

我正在使用默认的抽象配置:每个层次结构的表 如果有可能用EF 4.1解决我的问题,有人可以让我更聪明吗?

提前致谢, 桑德

1 个答案:

答案 0 :(得分:1)

如果我理解你的描述正确,那么你的模型看起来大致如此(我省略了关键属性等等):

public class Country
{
    public ICollection<State> States { get; set; }
}

public class State
{
    public ICollection<School> Schools { get; set; }
}

public abstract class School { ...  }

public class ElementarySchool : School { ... }

public class HighSchool : School
{
    public ICollection<DrivingCourse> DrivingCourses { get; set; }
}

public class DrivingCourse { ... }

你有一个DbContext,其中包含public DbSet<Country> Countries { get; set; }

现在您要加载所有Countries(或过滤的国家/地区集合),包括所有导航属性(尤其是DrivingCourses)。

我不知道这是否可以通过单一往返数据库(通过急切加载所有集合)。一个需要多次往返的解决方案可能就是这个:

// Load all Countries including `States` and `Schools` collection
// but not the `DrivingCourses` collection
var countryList = context.Countries
    .Include(c => c.States.Select(s => s.Schools))
    .ToList();

// Create in-memory list of all loaded Schools of type HighSchool
IEnumerable<HighSchool> highSchoolList =
    countryList.SelectMany(c =>
                  c.States.SelectMany(s => s.Schools.OfType<HighSchool>()));

// Explicitely load the DrivingCourses one by one
foreach (var item in highSchoolList)
    context.Entry(item).Collection(h => h.DrivingCourses).Load();

就像第一个想法一样。可能有更好的解决方案。

修改

在国家/地区DbSet上使用Load不会更改问题。 LoadToList()相同而没有实际返回结果,实体只是加载到上下文中。上面的代码可以这样重写:

context.Countries.Include(c => c.States.Select(s => s.Schools)).Load();

IEnumerable<HighSchool> highSchoolList =
    context.Countries.Local.SelectMany(c =>
                  c.States.SelectMany(s => s.Schools.OfType<HighSchool>()));

foreach (var item in highSchoolList)
    context.Entry(item).Collection(h => h.DrivingCourses).Load();

但这基本上和以前一样,并且它也没有解决在单个数据库往返中在第一个DrivingCourses语句中加载Load的问题。