基于抽象实体的急切加载嵌套导航问题(EF CTP5)

RPM*_*984 5 c# abstract-class eager-loading navigational-properties entity-framework-ctp5

我的EF模型的一部分看起来像这样:

在此输入图像描述

摘要:

  • 位置有很多帖子
  • Post是一个抽象
  • 讨论得出帖子
  • 讨论有很多评论

现在,我正试图实现的查询:

获取有关位置ID 1234的信息,包括与这些讨论相关的任何讨论和评论.

我可以得到讨论和这样的评论:

var discussions = ctx.Posts
                     .OfType<Discussion>()
                     .Include(x => x.Comments)
                     .ToList();
Run Code Online (Sandbox Code Playgroud)

但我似乎无法根据位置实体上的帖子导航获取它.

我试过这个:

var locationWithDiscussionsAndComments = ctx
                    .Locations
                    .Include(x => x.Posts
                                   .OfType<Discussion>()
                                   .Select(y => y.Comments))
                    .SingleOrDefault();
Run Code Online (Sandbox Code Playgroud)

哪个编译,但我得到错误:

System.ArgumentException:包含路径表达式必须引用实体定义的属性,也可以引用嵌套属性或对Select的调用.参数名称:路径

有任何想法吗?我可能会从帖子中"倒退":

var locationWithDiscussionsAndComments = ctx
                   .Posts
                   .Include(x => x.Location)
                   .OfType<Discussion>()
                   .Include(x => x.Comments)
                   .Where(x => x.LocationId == 1234)
                   .Select(x => x.Location)
                   .ToList();
Run Code Online (Sandbox Code Playgroud)

但就我的存储库而言,这在毛发和语义上都是错误的(我不应该通过帖子库来获取有关位置的信息).

有任何想法吗?

编辑

因此,在对它进行更大的思考之后,我意识到这OfType<T>是一个过滤操作.据我们所知,EF不支持使用预先加载进行过滤.唯一的选择是检索所有内容,或使用匿名类型投影.

我无法检索所有内容,因为涉及的元数据太多了.所以我正在尝试匿名类型投影.

Mor*_*avi 6

新的Query方法可能会帮助您:

var location = context.Locations.SingleOrDefault();

context.Entry(location)
       .Collection(l => l.Posts)
       .Query()
       .OfType<Discussion>()
       .Load();
Run Code Online (Sandbox Code Playgroud)


存储库实现:

我们可以向利用这种新方法的类添加一个新的LoadProperty泛型方法:Repository<T>QUery

public void LoadProperty<TElement>(T entity, 
        Expression<Func<T, ICollection<TElement>>> navigationProperty,
        Expression<Func<TElement, bool>> predicate) where TElement : class
{
    _context.Set<T>().Attach(entity);

    _context.Entry(entity)         
            .Collection(navigationProperty)
            .Query()
            .Where(predicate)
            .Load();
}
Run Code Online (Sandbox Code Playgroud)

使用LoadProperty方法:

Location location = _locationRepository.Find(1);
_locationRepository.LoadProperty(location, l => l.Posts, p => p is Discussion);
Run Code Online (Sandbox Code Playgroud)