【Entity Framework】你必须要了解EF中数据查询之数据加载

这篇具有很好参考价值的文章主要介绍了【Entity Framework】你必须要了解EF中数据查询之数据加载。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【Entity Framework】你必须要了解EF中数据查询之数据加载


【Entity Framework】你必须要了解EF中数据查询之数据加载,DotNet,# .Net Core,# Entity Framework,.netcore,c#,microsoft,asp.net,ef,数据库

一、概述

Entity Framework Core允许在模型中使用导航属性来加载关联实体。有三种常见的O/RM模式可用于加载关联数据。

  • 预先加载表示从数据库中加载关联数据,作为初始查询的一部分;
  • 显示加载表示稍后从数据库中显示加载关联数据;
  • 延迟加载表示在访问导航属性时,从数据库中以透明方式加载关联数据;

二、预先加载

可以使用Include方法来指定要包含在查询结果中的关联数据。如示例,结果中,结果中返回的blogs将使用关联的posts填充其posts属性。

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

Entity Framework Core 会根据之前已加载到上下文实例中的实体自动填充导航属性。 因此,即使不显式包含导航属性的数据,如果先前加载了部分或所有关联实体,则仍可能填充该属性。

可以在单个查询中包含多个关系的关联数据。

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

2.1 包含多个层级

使用ThenInclude方法可以依循关系包含多个层级的关联数据。以下示例加载了所有博客,其相关文章及每篇文章的作者。

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

可通过链式调用ThenInclude,进一步包含更深级别的关联数据。

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

可以将对来自多个级别和多个根的关联数据的所有调用合并到同一查询中。

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

你可能希望将已包含的某个实体的多个关联实体都包含进来。 例如,当查询 Blogs 时,你会包含 Posts,然后希望同时包含 PostsAuthorTags。 为了包含这两项内容,需要从根级别开始指定每个包含路径。 例如,Blog -> Posts -> AuthorBlog -> Posts -> Tags。 这并不意味着会获得冗余联接查询,在大多数情况下,EF 会在生成 SQL 时合并相应的联接查询。

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

2.2 经过筛选的包含

在应用包含功能来加载相关数据时,可对已包含的集合导航应用某些可枚举的操作,这样就可以对结果进行筛选和排序。

支持的操作包括:WhereOrderByOrderByDescendingThenByThenByDescendingSkipTake

应对传递到Include方法的Lambda中的集合导航应用这类操作。如下例所示:

using (var context = new BloggingContext())
{
    var filteredBlogs = context.Blogs
        .Include(
            blog => blog.Posts
                .Where(post => post.BlogId == 1)
                .OrderByDescending(post => post.Title)
                .Take(5))
        .ToList();
}

可对多次包含的每个导航应用相同的操作:

using (var context = new BloggingContext())
{
    var filteredBlogs = context.Blogs
        .Include(blog => blog.Posts.Where(post => post.BlogId == 1))
        .ThenInclude(post => post.Author)
        .Include(blog => blog.Posts.Where(post => post.BlogId == 1))
        .ThenInclude(post => post.Tags.OrderBy(postTag => postTag.TagId).Skip(3))
        .ToList();
}

三、显示加载

可以通过DbContext.Entry(...) API显示加载导航属性。

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

还可以通过执行返回关联实体的单独查询来显式加载导航属性。 如果已启用更改跟踪,则在查询具体化实体时,EF Core 将自动设置新加载的实体的导航属性以引用任何已加载的实体,并设置已加载实体的导航属性以引用新加载的实体。

3.1查询关联实体

可以获得表示导航属性内容的LINQ查询。

这使你可对查询应用其他运算符。示例:

using (var context = new BloggingContext())
{
    var blog = context.Blogs
        .Single(b => b.BlogId == 1);
    var postCount = context.Entry(blog)
        .Collection(b => b.Posts)
        .Query()
        .Count();
}

还可以筛选要加载到内存中的关联实体。

using (var context = new BloggingContext())
{
    var blog = context.Blogs
        .Single(b => b.BlogId == 1);
    var goodPosts = context.Entry(blog)
        .Collection(b => b.Posts)
        .Query()
        .Where(p => p.Rating > 3)
        .ToList();
}

四、延时加载

使用延迟加载的最简单方法是通过安装Microsoft.EntityFrameworkCore.Proxies包,并通过调用UseLazyLoadingProxies来启动该包。

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

或在使用 AddDbContext 时:

.AddDbContext<BloggingContext>(
    b => b.UseLazyLoadingProxies()
          .UseSqlServer(myConnectionString));

EF Core将为可被重写的任何导航属性启用延迟加载。

public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Post> Posts { get; set; }
}

public class Post
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public virtual Blog Blog { get; set; }
}

4.1 不使用代理进行延迟加载

不使用代理进行延迟加载的工作方式是将 ILazyLoader 注入到实体中,如实体类型构造函数中所述。例如:

public class Blog
{
    private ICollection<Post> _posts;

    public Blog()
    {
    }

    private Blog(ILazyLoader lazyLoader)
    {
        LazyLoader = lazyLoader;
    }

    private ILazyLoader LazyLoader { get; set; }

    public int Id { get; set; }
    public string Name { get; set; }

    public ICollection<Post> Posts
    {
        get => LazyLoader.Load(this, ref _posts);
        set => _posts = value;
    }
}

public class Post
{
    private Blog _blog;

    public Post()
    {
    }

    private Post(ILazyLoader lazyLoader)
    {
        LazyLoader = lazyLoader;
    }

    private ILazyLoader LazyLoader { get; set; }

    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public Blog Blog
    {
        get => LazyLoader.Load(this, ref _blog);
        set => _blog = value;
    }
}

此方法不要求实体类型为可继承的类型,也不要求导航属性必须是虚拟的,且允许通过new创建的实体实例在附加到上下文后可进行延迟加载。但它需要对Microsoft.EntityFrameworkCore.Abstractions包中定义的ILazyLoader服务的引用。此包包含所允许的最少的一组类型,以便将依赖此包时所产生的影响将到最低。不过,可以将ILazyLoader.Load方法以委托的形式注入,这样就可以完全避免依赖于实体类型的任何EF Core包。

public class Blog
{
    private ICollection<Post> _posts;

    public Blog()
    {
    }

    private Blog(Action<object, string> lazyLoader)
    {
        LazyLoader = lazyLoader;
    }

    private Action<object, string> LazyLoader { get; set; }

    public int Id { get; set; }
    public string Name { get; set; }

    public ICollection<Post> Posts
    {
        get => LazyLoader.Load(this, ref _posts);
        set => _posts = value;
    }
}

public class Post
{
    private Blog _blog;

    public Post()
    {
    }

    private Post(Action<object, string> lazyLoader)
    {
        LazyLoader = lazyLoader;
    }

    private Action<object, string> LazyLoader { get; set; }

    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public Blog Blog
    {
        get => LazyLoader.Load(this, ref _blog);
        set => _blog = value;
    }
}

上述代码使用 Load 扩展方法,以便更干净地使用委托:文章来源地址https://www.toymoban.com/news/detail-853985.html

public static class PocoLoadingExtensions
{
    public static TRelated Load<TRelated>(
        this Action<object, string> loader,
        object entity,
        ref TRelated navigationField,
        [CallerMemberName] string navigationName = null)
        where TRelated : class
    {
        loader?.Invoke(entity, navigationName);

        return navigationField;
    }
}

到了这里,关于【Entity Framework】你必须要了解EF中数据查询之数据加载的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • AI绘画你必须要知道5个tag进阶用法

    哈喽,大家好,我是阿宅,最近AI绘画也是很火,阿宅这几天也是静下心来好好研究了一下这个东西,确实好用啊,总所周知啊,这些前沿技术一直都是大厂来开拓和引导的,这不已经有消息说,某某大厂已经基于AI做好了一套完整的商业化流程了。         不管是小白还

    2023年04月15日
    浏览(33)
  • 初入mac电脑,你必须要知道这10款装机必备的宝藏软件

    初入mac电脑,不知道安装什么mac软件,这里整理了日常能给我工作和学习带来效率的10款软件分享给你们,个个都算得上是刚需,可以大大提高Mac的使用体验! 1、Downie 4 Mac 平台上非常好用的视频下载工具,支持1000 多个不同的视频网站,功能强大使用简单。 2、Magnet 这是一款

    2024年02月04日
    浏览(53)
  • 进阶--AI绘画里你必须要直到的controlnet模型使用方法

    哈喽,各位小伙伴们大家好,有一段时间没有更新了,最近也是忙着搬家忙着置办家具等等,今天终于得空,于是乎连忙抽空做了这期关于controlnet的使用教程。 因为最近我也是发现,controlnet对于AI绘画来说可真是太重要了,说白了,这个插件用好了,将会大大的提升我们的

    2024年02月04日
    浏览(65)
  • CSS基础:你必须要知道的行高属性 line-height

    作者: WangMin 格言: 努力做好自己喜欢的每一件事 对于初学CSS的同学来说,会有很多属性相关的疑问,行高属性 line-height一定是其中一个,因为它是CSS中非常重要的一个属性,这个属性改变元素在网页中的行高,让你的网页看起来更加整洁,美观。 什么是行高? CSS中的行高(

    2024年02月05日
    浏览(39)
  • 【C# .NET 】使用 Entity Framework Core 操作sqlite数据库

    添加包 EF Core design package   NuGet Gallery | Home 使用用于 EF Core 迁移和现有数据库中的反向工程(基架)的工具需要安装相应的工具包: 可在 Visual Studio 包管理器控制台中使用的 PowerShell 工具的 Microsoft.EntityFrameworkCore.Tools 跨平台命令行工具的 dotnet-ef 和 Microsoft.EntityFramewor

    2024年02月14日
    浏览(44)
  • .Net Core Entity Framework Core 的基础封装 -数据库操作拦截器

    自己制作的一个基于Entity Framework Core 的数据库操作拦截器,可以打印数据库执行sql,方便开发调试,代码如下: 运行结果如下:  

    2024年02月22日
    浏览(41)
  • C#:了解LINQ,简化数据查询和操作的强大工具

    以下是 LINQ(Language Integrated Query)中常见的及其作用,并给出一个示例以展示其执行结果: from :用于指定数据源,可以是集合、数组、数据库表等。 示例: where :用于筛选满足指定条件的元素。 示例: select :用于选择返回的结果集。 示例: orderby :用于对结果集

    2024年02月12日
    浏览(51)
  • 【Mysql】一篇带你了解数据定义,操作和查询语言

    目录 数据定义语言DDL(Data Definition Language) 一.对数据库的操作 二.对数据表的操作 数据操作语言DML(Data Manipulation Language) 一.添加 insert into 二.删除  delete 三.修改  update 数据查询语言DQL(Data Query Language) 一.查询 select 二. 1.between ... and ...(在....之间) 2.in, exists

    2024年02月12日
    浏览(73)
  • Entity Framework的最佳实践一

    Entity Framework (EF) Core 是轻量化、可扩展、 开源 和跨平台版的常用 Entity Framework 数据访问技术。 EF Core 可用作对象关系映射程序 (O/RM) EF Core API链接 Github地址   DbContext 的生存期从创建实例时开始,并在 释放 实例时结束。 通过依赖关系 为每个请求创建一个 ApplicationDbContext 

    2024年02月06日
    浏览(24)
  • 一个Entity Framework Core的性能优化案例

    本文提供一个EF Core的优化案例,主要介绍一些EF Core常用的优化方法,以及在优化过程中,出现性能反复的时候的解决方法,并澄清一些对优化概念的误解,例如AsNoTracking并不包治百病。 本文使用的是Dotnet 6.0和EF Core 7.0。 本文主要使用一个图书和作者的案例,用于介绍优化过

    2024年02月08日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包