在实体框架中使用紧急加载时,如何知道是否包括相关数据?

时间:2019-05-29 06:46:09

标签: c# entity-framework

我正在使用存储库模式的项目。我们正在使用Entity Framework从数据库中检索数据。要加载相关数据,我们使用Eager加载,这意味着我们必须明确地包括相关数据。

说我们要拥有所有博客及其相关文章,我们必须写:_dbContext.Blogs.include(b => b.Posts)

这样做的缺点是您只能看到存储库类中加载了哪些相关数据。

我试图在下面显示一个示例。这里的问题在类BlogViewModel.cs中出现,因为您尝试访问blogs.Posts,但是原始查询中不包含帖子。因此,如果您要获取相关数据,则必须检查查询的来源并查看其是否包含。

Repostiory.cs

  public IEnumerable<BlogDbModel> GetBlogs()
    {

        return _dbContext.Blogs.ToList();
    }

Service.cs

public IEnumerable<BlogViewModel> GetBlogs() {
  return _repository.Select(x => new BlogViewModel(x));
 }

BlogViewModel.cs

public class BlogViewModel {
  public BlogViewModel(BlogDbModel blogDbModel) {
    Name = blogDbModel.Name;
    Posts = blogDbModel.Posts;
}

  public string Name { get; set;}

  public IEnumberable<Posts> Posts {get; set;}

}

有人对此有一个明智的解决方案吗?如果您尝试访问未包含的数据,是否可能会给出编译错误?

我考虑过的两个选择是:

  1. 改为使用延迟加载。
  2. 始终从存储库返回IQueryable

谢谢

1 个答案:

答案 0 :(得分:1)

否,您没有任何选择可以在这种情况下产生编译错误。两种方式的数据都会在运行时加载。

延迟加载 假设您在视图中显示博客,帖子,评论,那么您需要在页面加载时加载所有内容。 启用lazyload并映射数据层查询中未包含的地图属性时,它将加载相关实体

public BlogViewModel(BlogDbModel blogDbModel) 
{
  Name = blogDbModel.Name;
  Posts = blogDbModel.Posts;
 }

如果启用lazyload并执行此操作,则将使用lazyload功能获取此信息。如果发布包含对User或任何其他对象的引用,它将也加载那些引用。 当您一开始需要所有内容时,不建议您使用lazyload,因为它会额外往返数据库。

可从存储库查询

我会说对视图模型的IQueryable是泄漏抽象。理想情况下,您的数据层应执行这些操作。向Viewmodel提供IQuerable<BlogDbModel>就像开发人员能够获取1Blogs => Post => User => Accounts1与此相关的任何内容。

恕我直言,我将编写视图所需的数据层方法。

LazyloadingEnabled = false;

public IEnumerable<BlogDbModel> GetBlogs()
{

    return _dbContext.Blogs.ToList();
}

public IEnumerable<BlogDbModel> GetBlogsAndPosts()
{

  return _dbContext.Blogs.Include("Posts").ToList();
}

//This will fetch only what is needed (You can customize to get columns what is needed)
public IEnumerable<NewCustomDTO> GetBlogsAndPostCount()
{

   return _dbContext.Blogs.Select(x=> NewCustomDTO
   {
       BlogName = x.BlogName,
       Count = x.Posts.Count(),
   });
}