为什么没有在.Include()上加载相关实体? [英] Why aren't related entities loaded on .Include()?

查看:111
本文介绍了为什么没有在.Include()上加载相关实体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以告诉我为什么相关的Article实体没有加载到.Include(a => a.Article)上的原因吗?即使ArticleId确实具有值,它们始终为NULL. FrontPageItemArticle之间的关系是1-0..1. Article可以不与FrontPageItem进行任何连接而存在,但是FrontPageItem必须具有一个Article.

Can anybody tell me why the related Article entities are not being loaded on .Include(a => a.Article)? They are always NULL even though ArticleId does indeed have a value. The relationship between FrontPageItem and Article is 1-0..1. An Article can exist without any connection to a FrontPageItem, but a FrontPageItem must have one Article.

在一个相当丑陋的解决方法中,我求助于foreach-遍历列表中的所有返回项,然后手动添加Article,如下面的索引方法所示.

In a rather ugly workaround, I have resorted to foreach-ing through all the returned items in the list and adding Article manually, as you can see in my index-method below.

public async Task<IActionResult> Index()
{
    List<FrontPageItem> items = await db.FrontPageItems
        .Include(a => a.Article)
            .ThenInclude(c => c.CreatedBy)
                .ThenInclude(m => m.Member)
        .Include(a => a.Article)
            .ThenInclude(e => e.EditedBy)
                .ThenInclude(m => m.Member)
        .Include(a => a.Article)
            .ThenInclude(e => e.PublishReadyBy)
                .ThenInclude(m => m.Member)
        .Include(p => p.WebPage)
        .OrderByDescending(o => o.DatePublished)
        .ToListAsync();
    // I don't want to foreach, but without it, Article is always NULL for all items.
    foreach (FrontPageItem item in items)
    {
        item.Article = await db.Articles
            .Where(a => a.Id == item.ArticleId).FirstOrDefaultAsync();
    }
    List<FrontPageItemViewModel> vm = 
        auto.Map<List<FrontPageItemViewModel>>(items);
    return View(vm);
}

这些是模型:

public class FrontPageItem
{
    public int Id { get; set; }
    // ... some more properties
    public int? ArticleId { get; set; }
    public Article Article { get; set; }

    public AdminUser CreatedBy { get; set; }
    public AdminUser EditedBy { get; set; }
    public AdminUser PublishedBy { get; set; }

}

public class Article
{
    public int Id { get; set; }
    // ... some more properties
    public int? FrontPageItemId { get; set; }
    public FrontPageItem FrontPageItem { get; set; }

    public AdminUser CreatedBy { get; set; }
    public AdminUser EditedBy { get; set; }
    public AdminUser PublishReadyBy { get; set; }
}

public class AdminUser
{
    public int Id { get; set; }
    // ... some more properties
    public int MemberId { get; set; }
    public Member Member { get; set; }
}

public class Member
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    // ... some more properties
    public AdminUser AdminUser { get; set; }
}

这是模型构建者:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Article>()
        .HasOne(p => p.FrontPageItem)
        .WithOne(i => i.Article)
        .HasForeignKey<Article>(b => b.FrontPageItemId);
}

推荐答案

首先,您需要了解急切加载,延迟加载,显式加载

First you need to understand about Eager Loading, Lazy Loading, Explicit loading

急切加载

快速加载可帮助您一次加载所有需要的实体; 也就是说,您的所有子实体都将在单个数据库调用中加载. 这可以通过使用Include方法来实现,该方法将 相关实体作为查询的一部分,并且大量数据是 一次加载.

Eager Loading helps you to load all your needed entities at once; i.e., all your child entities will be loaded at single database call. This can be achieved, using the Include method, which returs the related entities as a part of the query and a large amount of data is loaded at once.

延迟加载

这是实体框架的默认行为,其中子 仅在首次访问实体时才加载该实体.它 只是延迟了相关数据的加载,直到您提出要求为止.

It is the default behavior of an Entity Framework, where a child entity is loaded only when it is accessed for the first time. It simply delays the loading of the related data, until you ask for it.

显式加载

在实体框架中有一些选项可以禁用延迟加载. 关闭延迟加载"后,您仍然可以通过以下方式加载实体 显式调用相关实体的Load方法.有 加载方法参考的两种使用方法(加载单个导航 属性)和集合(以加载集合)

There are options to disable Lazy Loading in an Entity Framework. After turning Lazy Loading off, you can still load the entities by explicitly calling the Load method for the related entities. There are two ways to use Load method Reference (to load single navigation property) and Collection (to load collections)

因此,要加载关系实体,可以使用Microsoft.EntityFrameworkCore.Proxies包来启用延迟加载.因此,当您查询数据库EF时,EF将根据它们之间的关系返回关系数据

So to load relational entity you can use Microsoft.EntityFrameworkCore.Proxies package to enable lazy loading. So when you query database EF will return relational data base on their relationship

我的示例代码如下

services.AddDbContextPool<ApplicationDbContext>(options =>
  options.UseLazyLoadingProxies().UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
        b => b.MigrationsAssembly("AwesomeCMSCore")).UseOpenIddict());

如果您有任何问题,请告诉我

Please let me know if you have any problem

这篇关于为什么没有在.Include()上加载相关实体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆