ef 多个左联接查询_.NET 云原生架构师训练营(模块二 基础巩固 EF Core 查询)--学习笔记...

43a6ee7084080a58a2d1f0604ec9f22a.png

2.4.5 EF Core -- 查询

  • 关联数据加载
  • 客户端与服务端运算
  • 跟踪与不跟踪
  • 复杂查询运算
  • 原生 SQL 查询
  • 全局查询筛选器

关联数据加载

学员和助教都在项目分组中,调整模型,删除 Assistant

ProjectGroup 添加 Member 列表

public List<Member> Members { get; set; }

Member 添加 是否助教判断,分组信息

public bool IsAssistant { get; set; }public string GroupId { get; set; }public ProjectGroup Group { get; set; }

Task 添加 学员信息

public Member Member { get; set; }

接下来为每一个表添加一个控制器

一个 Project 对应多个 ProjectGroup

ProjectGroup

namespace LighterApi.Controller
{[ApiController][Route("api/[controller]")]public class ProjectGroupController : ControllerBase{private readonly LighterDbContext _lighterDbContext;public ProjectGroupController(LighterDbContext lighterDbContext){_lighterDbContext = lighterDbContext;}[HttpPost]public async Task<IActionResult> Create([FromBody] ProjectGroup group){_lighterDbContext.ProjectGroups.Add(group);await _lighterDbContext.SaveChangesAsync();return StatusCode((int) HttpStatusCode.Created, group);}[HttpGet][Route("{id}")]public async Task<IActionResult> GetAsync(string id, CancellationToken cancellationToken){var project = await _lighterDbContext.Projects.FirstOrDefaultAsync(p => p.Id == id, cancellationToken);return Ok(project);}}
}

迁移

dotnet ef migrations add RefactoryProjectEntitiesdotnet ef database update

Entity 主键添加自动生成

/// <summary>
/// 主键Id
/// </summary>
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id { get; set; }

启动程序,Postman 访问

b0431f581380884ffe56250dbe857fb1.png

ProjectController

[HttpGet]
[Route("{id}")]
public async Task<IActionResult> GetAsync(string id, CancellationToken cancellationToken)
{var project = await _lighterDbContext.Projects.FirstOrDefaultAsync(p => p.Id == id, cancellationToken);return Ok(project);
}

查询项目信息,发现分组信息 groups 为空

fd1b8f7714cca74110729a1e77675e33.png

因为 EF 默认不会查询关联数据,所以需要实现一下

ProjectController 获取项目时使用 Include

[HttpGet]
[Route("{id}")]
public async Task<IActionResult> GetAsync(string id, CancellationToken cancellationToken)
{var project = await _lighterDbContext.Projects.Include(p => p.Groups).FirstOrDefaultAsync(p => p.Id == id, cancellationToken);return Ok(project);
}

由于项目中有分组引用,分组中有项目引用,所以需要在序列化的时候处理循环引用

Startup

services.AddControllers().AddNewtonsoftJson(x=>x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);

这样就可以查到项目信息

1d1e37ee72e08818224d20922f0d1997.png

EF Core 为我们提供了三种加载数据的方式

  • 预先加载
  • 显式加载
  • 延迟加载

加载相关数据:https://docs.microsoft.com/zh-cn/ef/core/querying/related-data/

预先加载

预先加载表示从数据库中加载关联数据,作为初始查询的一部分。

在以下示例中,结果中返回的blogs将使用关联的posts填充其 Posts 属性。

using (var context = new BloggingContext())
{var blogs = context.Blogs.Include(blog => blog.Posts).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();
}

ProjectController

// 显式加载
var project = await _lighterDbContext.Projects.FirstOrDefaultAsync(p => p.Id == id, cancellationToken);
await _lighterDbContext.Entry(project).Collection(p => p.Groups).LoadAsync(cancellationToken);

延迟加载

延迟加载表示在访问导航属性时,从数据库中以透明方式加载关联数据。

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

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

或在使用 AddDbContext 时:

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

EF Core 接着会为可重写的任何导航属性(即,必须是 virtual 且在可被继承的类上)启用延迟加载。 例如,在以下实体中,Post.Blog 和 Blog.Posts 导航属性将被延迟加载。

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

Project

public virtual ICollection<ProjectGroup> Groups { get; set; }

ProjectController

// 延迟加载
project.Groups// 引用到属性时才加载

客户端与服务端运算

客户端与服务端运算:https://docs.microsoft.com/zh-cn/ef/core/querying/client-eval

由于 SQL Server 提供程序不了解此方法的实现方式,因此无法将其转换为 SQL。 查询的所有其余部分是在数据库中评估的,但通过此方法传递返回的 URL 却是在客户端上完成。

var blogs = context.Blogs.OrderByDescending(blog => blog.Rating).Select(blog => new{Id = blog.BlogId,Url = StandardizeUrl(blog.Url)// 服务端转换SQL,不了解客户端方法实现}).ToList();public static string StandardizeUrl(string url)
{url = url.ToLower();if (!url.StartsWith("http://")){url = string.Concat("http://", url);}return url;
}

需要区分数据运算最终在客户端,还是服务端运行

循环中获取分组会导致多次查询数据库

foreach (var project in _lighterDbContext.Projects)
{project.Groups// 多次查询数据库
}

应该一次性查询

var projects = _lighterDbContext.Projects.ToList();

跟踪与不跟踪

跟踪与不跟踪:https://docs.microsoft.com/zh-cn/ef/core/querying/tracking

默认情况下,跟踪返回实体类型的查询。 这表示可以更改这些实体实例,然后通过 SaveChanges() 持久化这些更改。

非跟踪查询

var blogs = context.Blogs.AsNoTracking().ToList();

还可以在上下文实例级别更改默认跟踪行为:

context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;var blogs = context.Blogs.ToList();

复杂查询运算

复杂查询运算:https://docs.microsoft.com/zh-cn/ef/core/querying/complex-query-operators

联接

var query = from photo in context.Set<PersonPhoto>()join person in context.Set<Person>()on photo.PersonPhotoId equals person.PhotoIdselect new { person, photo };

GroupJoin

var query = from b in context.Set<Blog>()join p in context.Set<Post>()on b.BlogId equals p.PostId into groupingselect new { b, grouping };

SelectMany

var query = from b in context.Set<Blog>()from p in context.Set<Post>()select new { b, p };

GroupBy

var query = from p in context.Set<Post>()group p by p.AuthorId into gselect new{g.Key,Count = g.Count()};

Left Join

var query = from b in context.Set<Blog>()join p in context.Set<Post>()on b.BlogId equals p.BlogId into groupingfrom p in grouping.DefaultIfEmpty()select new { b, p };

原生 SQL 查询

原生 SQL 查询:https://docs.microsoft.com/zh-cn/ef/core/querying/raw-sql

var blogs = context.Blogs.FromSqlRaw("SELECT * FROM dbo.Blogs").ToList();

全局查询筛选器

全局查询筛选器:https://docs.microsoft.com/zh-cn/ef/core/querying/filters

modelBuilder.Entity<Blog>().HasQueryFilter(b => EF.Property<string>(b, "_tenantId") == _tenantId);
modelBuilder.Entity<Post>().HasQueryFilter(p => !p.IsDeleted);

所有实体都继承了基类 Entity,所以这样会把过滤器添加在所有查询上面

LighterDbContext

modelBuilder.Entity<Entity>().HasQueryFilter(x => x.TenantId == "");

GitHub源码链接:

https://github.com/MINGSON666/Personal-Learning-Library/tree/main/ArchitectTrainingCamp/LighterApi

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/505606.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用友 无法正确解析服务器,用友T3软件登陆软件时提示:“可能无法正确解析服务器名称或者相应的端口被禁用,请尝试输入服务器的IP地址”?...

你好&#xff01;现在想要建立2015年的年度账&#xff0c;但新建年度账 是2016年 怎么解决&#xff1f; 你好&#xff01;现在想要建立2015年的年度账&#xff0c;但新建年度账 是2016年 怎么解决&#xff1f;[]您账才 做到2014年&#xff0c;要建立2015年度账&#xff1f;服务…

来自网页的消息服务器繁处理忙,EventSource 对象用于接收服务器发送事件通知,是网页自动获取来自服务器的更新...

//--------------------------------客户端代码-----------------------------if(typeof(EventSource) ! "undefined") {var source new EventSource("../api/v1/event.source");source.onmessage function(event) {$("#content_event").html(…

linux定向查日志_linux日志查找技巧

基础命令# 查询日志尾部最后10行的日志;tail -n 10 test.log#查询10行之后的所有日志;tail -n 10 test.log# 查询日志文件中的头10行日志;head -n 10 test.log# 查询日志文件除了最后10行的其他所有日志;head -n -10 test.log# 查看日志的尾部&#xff0c;并刷新显示日志变动。…

三国杀服务器改名 插图修改,《三国杀》大幅修改的武将——新旧两版,你更喜欢哪一位...

三国杀中&#xff0c;某些武将因为太强或者太弱&#xff0c;不能适应游戏环境&#xff0c;都会进行修改&#xff0c;例如&#xff1a;李丰、马良、伏皇后、曹冲等等&#xff0c;但这些武将修改之后&#xff0c;原有武将就淘汰了。其实&#xff0c;还有一类武将&#xff0c;技能…

php开源mvccms_轻松理解MYSQL MVCC 实现机制

1. MVCC简介1.1 什么是MVCCMVCC是一种多版本并发控制机制。1.2 MVCC是为了解决什么问题?大多数的MYSQL事务型存储引擎,如,InnoDB&#xff0c;Falcon以及PBXT都不使用一种简单的行锁机制.事实上,他们都和MVCC–多版本并发控制来一起使用.大家都应该知道,锁机制可以控制并发操作…

苹果电脑mac_清理Mac苹果电脑DNS缓存

说到清理苹果电脑想必不少网友会说苹果电脑不需要清理&#xff0c;但事实情况是现在对于“苹果电脑清理”的这个话题一直在不断地热议中&#xff0c;虽说Mac OS X系统它的优化比较好&#xff0c;很多小的无效数据文件会自动归类清除&#xff0c;但很多时候一些稍大的数据文件仍…

学python需要记笔记吗_开始学python,一些笔记

想想其实应该还是像在linux下一样在命令行下测试的&#xff0c;但是先跟着一个教程在IDE上试试手吧。1. 中文编码&#xff0c;我用的是python2.6.9 加两行注释&#xff1a;#!/usr/bin/python2.6# -*- coding: utf-8 -*-我原以为第一行是Python的安装目录&#xff0c;所以找了很…

鼠标追踪没用_【擺评】赛睿里最好用的小手鼠标---Rival 3

拿到这鼠标真的是有段时间了&#xff0c;深度体验了一个多月。先说&#xff0c;这是我用过所有赛睿鼠标里最喜欢的鼠标&#xff0c;虽然它不贵&#xff0c;虽然它是有线的&#xff0c;但真的舒服&#xff01;可能我也没用过几个赛睿的鼠标&#xff0c;仅有以下几款&#xff0c;…

java代码ftp重命名未生效_java使用apache commons连接ftp修改ftp文件名失败原因

今天被ftp上中文名修改坑了好久项目用的是 apache commons 里的 FtpClient 实现的对ftp文件的上传下载操作&#xff0c;今天增加了业务要修改ftp上的文件名&#xff0c;然后就一直的报错&#xff0c;问题是它修改名字的方法只返回一个boolean&#xff0c;没有异常&#xff0c;这…

zynq中mgtx应用_Zynq7000系列之芯片引脚功能综述

很多人做了很久的FPGA&#xff0c;知道怎么去给信号分配引脚&#xff0c;却对这些引脚的功能及其资源限制知之甚少&#xff1b;在第一章里对Zynq7000系列的系统框架进行了分析和论述&#xff0c;对Zynq7000系列的基本资源和概念有了大致的认识&#xff0c;然而要很好地进行硬件…

mysql存储过程触发器_MySQL存储过程及触发器

一、存储过程存储过程的基本格式如下&#xff1a;-- 声明结束符-- 创建存储过程DELIMITER $ -- 声明存储过程的结束符CREATE PROCEDURE pro_test() --存储过程名称(参数列表)BEGIN-- 可以写多个sql语句; -- sql语句流程控制SELECT * FROM employee;END $ -- 结束 结束符-- 执行…

mysql 扩展存储过程_MySQL4:存储过程和函数

什么是存储过程简单说&#xff0c;存储过程就是一条或多条SQL语句的集合&#xff0c;可视为批文件&#xff0c;但是起作用不仅限于批处理。本文主要讲解如何创建存储过程和存储函数以及变量的使用&#xff0c;如何调用、查看、修改、删除存储过程和存储函数等。使用的数据库和表…

netcore quartz job用不了services_.NetCore开源集成框架

GitHub地址&#xff1a;https://github.com/zwl568633995/AspNetCoreScaffolding&#xff08;感兴趣的Fork给个小星星吧~&#xff09;AspNetCoreScaffolding本框架在.netCore和.netStandard的基础上&#xff0c;集成了多种中间件.NetCore集成框架&#xff0c;即开即用如果对您有…

mysql基准性能测试标准_mysql性能测试与优化——(一),基准测试套件

笔者英语不好&#xff0c;又没人翻译&#xff0c;只好自己动手&#xff0c;希望大家多提意见&#xff0c;我好及时修改&#xff0c;以免误导他人。本文仅供参考&#xff0c;笔者对使用者产生的任何后果&#xff0c;概不负责。 转载请注明出处&#xff01;正文&#xff1a;The…

python合并数组输出重复项_python进行数组合并的方法

python的数组合并在算法题中用到特别多&#xff0c;这里简单总结一下&#xff1a;假设有a1和a2两个数组&#xff1a;a1[1,2,3]a2[4,5,6]合并方式1. 直接相加#合并后赋值给新数组a3a3 a1 a22. extend#调用此方法&#xff0c;a1会扩展成a1和a2的内容a1.extend(a2)3. 列表表达式…

mysql更新代码_mysql update语句的用法

1. 单表的UPDATE语句&#xff1a;UPDATE [LOW_PRIORITY] [IGNORE] tbl_nameSET col_name1expr1 [, col_name2expr2 ...][WHERE where_definition][ORDER BY ...][LIMIT row_count]2. 多表的UPDATE语句UPDATE [LOW_PRIORITY] [IGNORE] table_referencesSET col_name1expr1…

安装版mysql错误2_【gem安装】mysql2错误

错误信息Gem::Ext::BuildError: ERROR: Failed to build gem native extension./home/jaylin/.rvm/rubies/ruby-2.2.1/bin/ruby -r ./siteconf20150423-6190-1ocfncu.rb extconf.rbchecking for ruby/thread.h... yeschecking for rb_thread_call_without_gvl() in ruby/thread…

linux 父子进程 资源_linux 父子进程 资源_实验4 Linux父子进程同步

实验4 Linux父子进程同步【实验目的】(1)熟悉在c语言源程序中使用linux所提供的系统调用界面的方法。(2)理解同步的概念。(3)使用系统调用wait()和exit()&#xff0c;实现父子进程同步。【实验原理/实验基础知识】一、同步在多道系统中&#xff0c;一个进程相对于另一个进程的…

mysql事件循环执行,Node.js MySQL连接,查询顺序和事件循环

Lets see this exampleconn.query(SET v 1;, (err) > {conn.query(SELECT v;, (err, res) > {// res contains v 1 or 2 ?});});conn.query(SET v 2;, (err) > {conn.query(SELECT v;, (err, res) > {// res contains v 1 or 2 ?});});Does mysql/mysql2 nod…

mysql执行一条语句会加锁吗_一条简单的更新语句,MySQL是如何加锁的?

看如下一条sql语句&#xff1a;# table T (id int, name varchar(20))delete from T where id 10&#xff1b;MySQL在执行的过程中&#xff0c;是如何加锁呢&#xff1f;在看下面这条语句&#xff1a;select * from T where id 10&#xff1b;那这条语句呢&#xff1f;其实这…