实体框架核心 - 加载包含相关实体的相关实体的问题

时间:2017-02-22 09:03:08

标签: entity-framework-core

我在Chris Sakell的博客here之后使用实体框架核心。

他使用泛型来管理他的存储库以及他用于所有其他存储库的基本存储库。

基本存储库的一部分具有以下代码,用于检索单个实体,该实体还使用includeProperties选项下载相关实体。以下是检索单个项目的通用代码。

public T GetSingle(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includeProperties)
{
    IQueryable<T> query = _context.Set<T>();

    foreach (var includeProperty in includeProperties)
    {
        query = query.Include(includeProperty);
    }

    return query.Where(predicate).FirstOrDefault();
}

我在一个附加了许多作业的客户端表上使用它。

这就是我构建代码的方式。

    public ClientDetailsViewModel GetClientDetails(int id)
    {
        Client _client = _clientRepository
            .GetSingle(c => c.Id == id, c => c.Creator, c => c.Jobs, c => c.State);

        if(_client != null)
        {
            ClientDetailsViewModel _clientDetailsVM = mapClientDetailsToVM(_client);
            return _clientDetailsVM;
        }
        else
        {
            return null;
        }
    }

该行:

.GetSingle(c => c.Id == id, c => c.Creator, c => c.Jobs, c => c.State);

成功检索创建者状态和作业的值。

但是,没有为与“作业”相关联的相关实体检索任何内容。

enter image description here

具体而言,JobVisits是对工作的访问的集合。

为了完整起见,我在

下面添加了“job”和“jobvisit”实体
public class Job : IEntityBase
{
    public int Id { get; set; }

    public int? ClientId { get; set; }
    public Client Client { get; set; }

    public int? JobVisitId { get; set; }
    public ICollection<JobVisit> JobVisits { get; set; }

    public int? JobTypeId { get; set; }
    public JobType JobType { get; set; }

    public int? WarrantyStatusId { get; set; }
    public WarrantyStatus WarrantyStatus { get; set; }

    public int? StatusId { get; set; }
    public Status Status { get; set; }

    public int? BrandId { get; set; }
    public Brand Brand { get; set; }

    public int CreatorId { get; set; }
    public User Creator { get; set; }

    ....
}

public class JobVisit : IEntityBase
{
    ...
    public int? JobId { get; set; }
    public Job Job { get; set; }

    public int? JobVisitTypeId { get; set; }
    public JobVisitType VisitType { get; set; }
}

我的问题是,如何修改上面的存储库代码以及GetSingle使用,以便我还可以加载相关的enitities JobVisit集合以及其他相关的单个实体BrandJobType

1 个答案:

答案 0 :(得分:1)

无需检索导航属性以与“作业”关联。这就是为什么有些属性是null。默认情况下,.Include(property);只有1级深度,这是一件好事。它可以防止您的查询获取数据库的所有数据。

如果您想要包含多个级别,则应在.ThenInclude(property)之后使用.Include(property)。来自documentation

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
            .ThenInclude(post => post.Author)
        .ToList();
}

我的建议是您的方法public T GetSingle(...)很好,我不会更改它以包含更深层次。而不是那样,你可以简单地使用显式加载。来自documentation

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();
}