在EF Core中将每个项目的属性包括在集合中

时间:2019-04-02 14:02:53

标签: c# .net-core entity-framework-core

我有一个带有EntityFramework的.Net Core 2.2项目,以及一个具有许多嵌套属性(无论是单个对象还是集合)的模型。

我已经启用了延迟加载,现在我只想选择性地加载我在控制器中已插入的对象树的部分。

当我使用.include()时,一切都很好,直到我想包含一个集合属性,并且对于该集合中的每个项目,我都想包含一个相关实体。

阅读文档时,我使用了这种方法:

var mainObj = _db.MyEntityA.AsNoTracking()
            .Include(e => e.MyEntityB)
            .Include(e => e.CollectionOfEntityC.Select((MyEntityC ce) => ce.MyEntityD))

当我运行它时,它会给出如下信息:

InvalidOperationException: The Include property lambda expression 'e => {from EntityC ce in e.CollectionOfEntityC select [ce].MyEntityD}' is invalid. The expression should represent a property access: 't => t.MyProperty'. To target navigations declared on derived types, specify an explicitly typed lambda parameter of the target type, E.g. '(Derived d) => d.MyProperty'.

所以我尝试添加演员表:

var mainObj = _db.MyEntityA.AsNoTracking()
            .Include(e => e.MyEntityB)
            .Include(e => e.CollectionOfEntityC.Select((MyEntityC ce) => ce.MyEntityD))

但没有任何改变。

我尝试通过这种方式使用.ThenInclude():

    var mainObj = _db.MyEntityA.AsNoTracking()
            .Include(e => e.MyEntityB)
            .ThenInclude(e => e.Select((MyEntityC ce) => ce.MyEntityD))

有无演员表都没有改变。

最后,合理地讲,如果删除该导航属性,则会出现以下异常:

Error generated for warning 'Microsoft.EntityFrameworkCore.Infrastructure.DetachedLazyLoadingWarning: An attempt was made to lazy-load navigation property 'MyEntityD' on detached entity of type 'MyEntityCProxy'. Lazy-loading is not supported for detached entities or entities that are loaded with 'AsNoTracking()'.

我正在移植到.Net Core上的同一场景,在.Net Framework EF上按预期工作。

编辑:

探索正确提及的重复项,我只想添加一些其他相关方面。

@StriplingWarrior的回答很好;我使用.ThenInclude()而不是.Select()修复了我的代码。现在一切都建立了,但是:

  • IntelliSense不能帮助在ThenInclude()内部编写代码
  • 如果我离开AsNoTraking(),则必须禁用DetachedLazyLoadingWarning
  • 如果我删除AsNoTracking() EF跟踪更改,我不希望它跟踪(我想要一个复杂对象的只读快照)

1 个答案:

答案 0 :(得分:2)

It looks like这就是您应该使用ThenInclude的方式:

var mainObj = _db.MyEntityA.AsNoTracking()
        .Include(e => e.MyEntityB)
        .Include(e => e.CollectionOfEntityC)
        .ThenInclude(ce => ce.MyEntityD);