如何使用EF Core加载导航属性?

12
在EF6中,我们可以做到以下几点:
context.Set<TEntity>().Attach(entity);
context.Entry(entity).Collection("NavigationProperty").Load();

由于EF Core正在“100%严格类型化”,他们已经移除了Collection函数。那么我们应该使用什么替代品呢?
如何为一个已附加的实体加载导航属性?也就是说,我是否有一种方法可以在已检索到的实体上调用类似.Include()和.ThenInclude()的东西?

1
此API将在EF Core 1.1中回归。 - bricelam
3个回答

20

显式加载(Explicit Loading)是在 Entity Framework Core v1.1 中新增的功能。 请查看 Microsoft Docs

来自文档:

using (var context = new BloggingContext())
{
    var blog = context.Blogs
    .Single(b => b.BlogId == 1);

    context.Entry(blog)
        .Collection(b => b.Posts)
        .Load();

    context.Entry(blog)
        .Reference(b => b.Owner)
        .Load();
}

20

你有3种方法:

1. 前期加载

例如:

var blogs = context.Blogs
    .Include(blog => blog.Posts)
    .ToList();

2. 显式加载

e.g.

var blog = context.Blogs
    .Single(b => b.BlogId == 1);

context.Posts
    .Where(p => p.BlogId == blog.BlogId)
    .Load();

3. 延迟加载 (自 EF Core 2.1 起)

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseLazyLoadingProxies()
        .UseSqlServer(myConnectionString);

您可以在此处阅读更多信息:Loading Related Data

更新:

您可以使用 TrackGraph API 来处理这种用例。这是链接:添加/附加的图形行为

另一个链接:DbSet.Add/Attach和图形行为


请查看更新 - Sampath
感谢您的评论和链接。我看到在ATTACH期间更改跟踪更改行为有一定意义,但不明白它如何与阻止加载已附加实体的导航属性相关。也许您对此有自己的想法? - Roman Pokrovskij
1
如果您关心阅读第一个提供的链接,特别是显式加载部分,它对应于您所询问的EF6功能,您会注意到第一句话是显式加载在EF Core中还没有第一类API,并附有一个跟踪此功能的链接。因此,它不是一个简化的功能,只是尚未实现。该链接还包含一个解决方法(由Sampath复制/粘贴),您只需要理解并将其用于您的用例即可。 - Ivan Stoev
你不会找到一个能理解“显式加载还没有一流的API”这句话的人。什么是“一流的API”?为什么拥有“一流的API”而不仅仅是“API”很重要?但如果显式加载与上下文中的实体一样,附带实体的示例可以正常工作,那么对我来说就没问题了。我一定会检查它的工作原理和生成的SQL。 - Roman Pokrovskij
1
@RomanPokrovskij 哈哈,我明白你的意思:) 嗯,英语不是我的母语,对我来说它听起来就像是“我们目前还不支持原生的,这是你的解决方法blah-blah(感谢你成为我们的alpha测试人员)” :) - Ivan Stoev
显示剩余3条评论

1
请看下面的代码,
我正在将数据插入到UserRef表中,还有另一个我们有许多2个多关系的表。
public void AddUser(User user, IEnumerable<UserSecurityQuestion> securityQuestion, string password)
    {
        var userModel = _mapper.Map<User, UserRef>(user);
        userModel.CreateTime = DateTime.Now;

        userModel.UserNewsLetterMaps.ToList().ForEach(u => this._context.UserNewsLetterMaps.Add(u));            
        this._context.RoleRefs.Attach(new RoleRef() { RoleId = (int)user.UserRole, UserRefs = new List<UserRef> { userModel } });
        userModel.ResidenceStatusRefs.ToList().ForEach(u => this._context.ResidenceStatusRefs.Attach(u));
        this._context.UserRefs.Add(userModel);
        this.Save();
    }

是的,类似这样的方法应该可以:从上下文中加载实体,然后在两个“attached”实体和新的“get from context”实体之间以某种方式调整“navigationPropertis”...如果我正确理解了代码...但这样做实在太丑陋、太令人悲伤了... - Roman Pokrovskij
看起来我得到了“显式加载”也适用于附加实体。应该尝试一下。 - Roman Pokrovskij

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接