简体   繁体   English

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

[英]Problem with Eager Loading Nested Navigation Based on Abstract Entity (EF CTP5)

I a portion of my EF model that looks like this: 我的EF模型的一部分看起来像这样:

在此处输入图片说明

Summary: 摘要:

  • Location has many Posts 位置有很多帖子
  • Post is an abstract class 帖子是一个抽象
  • Discussion derives from Post 帖子讨论导出
  • Discussions have many Comments 讨论有很多评论

Now, the query i'm trying to achieve: 现在,我正在尝试实现的查询:

Get information about Location Id 1234, including any Discussions and Comments associated with those Discussions. 获取有关位置ID 1234的信息,包括与这些讨论相关的任何讨论和评论。

I can get discussions and the comments like this: 我可以得到这样的讨论和评论:

var discussions = ctx.Posts
                     .OfType<Discussion>()
                     .Include(x => x.Comments)
                     .ToList();

But i can't seem to get it based on the Posts navigation on the Location entity. 但是我似乎无法基于Location实体上的Posts导航来获取它。

I've tried this: 我已经试过了:

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

Which compiles, but i get the error: 哪个编译,但我得到错误:

System.ArgumentException: The include path expression must refer to a property defined by the entity, optionally also with nested properties or calls to Select. System.ArgumentException:包含路径表达式必须引用由实体定义的属性,还可以使用嵌套属性或对Select的调用。 Parameter name: path 参数名称:路径

Any ideas? 有任何想法吗? I could probably go "backwards" from the Posts: 我可能可以从帖子中“退后”:

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

But that is both hairy and semantically wrong in terms of my repositories (i shouldn't have to go through a post repository to get information about a location). 但是,就我的存储库而言,这既是毛茸茸的,又在语义上是错误的(我不必经过邮政存储库即可获取有关位置的信息)。

Any ideas? 有任何想法吗?

EDIT 编辑

So after having a bigger think about it, i realized that OfType<T> is a filter operation. 因此,在考虑了一下之后,我意识到OfType<T>是一个过滤操作。 As as we know, EF does not support filtering with eager loading. 众所周知,EF不支持带有紧急加载的过滤。 The only options are retrieving everything , or using anonymous type projection. 唯一的选择是检索所有内容 ,或使用匿名类型投影。

No way i can retrieve everything, as there is far too much meta data involved. 我无法检索所有内容,因为涉及太多的元数据。 So i'm attempting the anonymous type projection. 所以我正在尝试匿名类型投影。

The new Query method might help you: 新的查询方法可能会帮助您:

var location = context.Locations.SingleOrDefault();

context.Entry(location)
       .Collection(l => l.Posts)
       .Query()
       .OfType<Discussion>()
       .Load();


Repository Implementation: 存储库实现:

We can add a new LoadProperty generic method to the Repository<T> class that leverages this new QUery method: 我们可以向Repository<T>类添加一个新的LoadProperty通用方法,该方法利用了这个新的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();
}

Using the LoadProperty method: 使用LoadProperty方法:

Location location = _locationRepository.Find(1);
_locationRepository.LoadProperty(location, l => l.Posts, p => p is Discussion);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM