EFCore之增删改查

1. 连接数据库

通过依赖注入配置应用程序,通过startup类的ConfigureService方法中的AddDbContext将EFCore添加到依赖注入容器

public void ConfigureServices(IServiceCollection services)
{services.AddControllers();services.AddDbContext<OpenDbContext>(options => options.UseMySql(Configuration["DbConfig:Mysql:ConnectionString"]);
}

将名为 OpenDbContext的 DbContext 子类注册到依赖注入容器的Scope生命周期。上下文配置为使用MySQL数据库提供程序,并从配置中读取数据库连接字符串。

OpenDbContext类必须公开具有 DbContextOptions参数的公共构造函数。这是将 AddDbContext 的上下文配置传递到 DbContext 的方式。

    public class OpenDbContext : DbContext{public OpenDbContext(DbContextOptions options) : base(options){}public DbSet<User> Users { get; set; }public DbSet<Score> Scores { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){//另一种配置连接数据库的方式//optionsBuilder.UseMySql("连接数据库", ServerVersion.AutoDetect("连接数据库字符串"));//显示敏感数据日志optionsBuilder.EnableSensitiveDataLogging(true);}protected override void OnModelCreating(ModelBuilder modelBuilder){//属性配置//modelBuilder.Entity<User>().Property(t => t.Account).IsRequired().HasMaxLength(20).HasComment("帐号");//种子数据设置//modelBuilder.Entity<User>().HasData(new User { Account="种子"});//批量添加etc的操作modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());base.OnModelCreating(modelBuilder);}}

然后将OpenDbContext通过构造函数注入的方式注入到应用程序的控制器或者其他服务中使用。

关于连接数据库可以参考另一个文章:.Net之生成数据库全流程

2. 操作数据库

    context.Database.EnsureDeleted();//删除数据库,如果存在,如果没有权限,则引发异常context.Database.EnsureCreated();//如果数据库不存在,创建数据库并初始化数据库架构,如果存在任何表,则不会初始化架构context.Database.Migrate();//根据迁移文件,迁移数据库

3. 查询操作

3.1 基础查询

db.Set<UserInfor>().ToList();//查询表达式
var account = (from u in _context.Userswhere u.Id == idselect u.Account).ToList();//查询单个
_context.Movie.FirstOrDefaultAsync(m => m.ID == id);
_context.Movie.FindAsync(id); 
//查询指定列
_context.Set<User>().AsNoTracking().Where(t=>t.Id=="11").Select(t => new { t.Account, t.PassWord }).FirstOrDefaultAsync();// 预先加载查询
var blogs = context.Blogs.Include(blog => blog.Posts).ToList();
// 包含多个层级的查询
var blogs = context.Blogs.Include(blog => blog.Posts).ThenInclude(post => post.Author).ToList();

SingleOrDefaultAsync 与FirstOrDefaultAsync

如果有多个实体符合筛选部分, SingleOrDefaultAsync 将引发异常。

如果有多个实体符合筛选部分, FirstOrDefaultAsync 不引发异常。

FindAsync

在大部分基架代码中,FindAsync 可用于替代 FirstOrDefaultAsync ,查找具有主键 (PK) 的实体。如果具有 PK 的实体正在由上下文跟踪,会返回该实体且不向 DB 发出请求。

3.2 跟踪和非跟踪查询

跟踪行为决定了EFCore是否将有些实体的信息保存在其更改更跟踪器中。如果已跟踪某个实体,则该实体中检测到的任何更改都会在SaveChanges()时候保存到数据库,

不跟踪没有主键的实体类型。

# 跟踪查询
_context.Set<User>().ToListAsync();# 非跟踪查询
_context.Set<User>().AsNoTracking().ToListAsync();

默认是跟踪查询

3.3 条件查询

3.3.1 不支持异步方案

            Func<User, bool> express = x => true;       if (!string.IsNullOrWhiteSpace(dto.Data)){express = x => x.Mobile == dto.Data;}string userid = "";if (!string.IsNullOrWhiteSpace(userid)){express = x => x.UserId == userid;}var bbb = _dbContext.Set<User>().Where(express).FirstOrDefault();

3.3.2 支持异步方案

            Expression<Func<User, bool>> express = x => true;if (!string.IsNullOrWhiteSpace(dto.Data)){express = x => x.Mobile == dto.Data;}var bbb = await _dbContext.Set<User>().Where(express).ToListAsync();

3.4 原生SQL查询

可使用 FromSqlRaw 扩展方法基于原始 SQL 查询开始 LINQ 查询。FromSqlRaw 只能在直接位于 DbSet<> 上的查询根上使用。

3.4.1 基本原生SQL查询

var blogs = context.Blogs.FromSqlRaw("select * from user").ToList();// 执行存储过程
var blogs = context.Blogs.FromSqlRaw("EXECUTE dbo.GetMostPopularBlogs").ToList();

2.x里面使用FromSql,在3.x里面使用FromSqlRow方法

3.4.2 参数化查询

3.4.2.1 SQL注入

首先我们编写一个简单的SQL注入示例,比如就注入我们根据ID查询的语句,输入ID为:ididid' or '1'='1

    var strSql = string.Format("select * from user where Id='{0}'", "ididid' or '1'='1");var query = await _context.Set<User>().FromSqlRaw(strSql).ToListAsync();Console.WriteLine(JsonConvert.SerializeObject(query));

生成语句

      select * from user where Id='ididid' or '1'='1'
[{"Account":"张三","PassWord":"123456","CreateTime":"2021-05-20T22:53:44.778101","IsValid":false,"Id":"1395392302788120576"},{"Account":"李四","PassWord":"123456","CreateTime":"2021-05-20T22:53:44.849376","IsValid":false,"Id":"1395392303090110464"},{"Account":"王五","PassWord":"123456","CreateTime":"2021-05-20T22:53:44.849425","IsValid":false,"Id":"1395392303090110467"}]

3.4.2.2 FromSqlRaw参数化

通过参数化查询,防止SQL注入问题

    //sql语句参数化查询,防止SQL注入    var strSql = "select * from user where Id=@id";var parameter = new MySqlParameter[] {new MySqlParameter("@id","1395392302788120576"),};var query = await _context.Set<User>().FromSqlRaw(strSql, parameter).ToListAsync();

或者

    var strSql = "select * from user where Id={0}";var query = await _context.Set<User>().FromSqlRaw(strSql, "1395392302788120576").ToListAsync();Console.WriteLine(JsonConvert.SerializeObject(query));// 生成SQLselect * from user where Id=@p0[{"Account":"张三","PassWord":"123456","CreateTime":"2021-05-20T22:53:44.778101","IsValid":false,"Id":"1395392302788120576"}]

通过占位符形式提供额外的参数,看上去类似于String.Format语法,但是提供的值包装在DbParameter中。可以防止SQL注入

3.4.2.3 FromSqlInterpolated参数化

FromSqlInterpolated 类似于 FromSqlRaw,但你可以借助它使用字符串内插语法。与 FromSqlRaw 一样,FromSqlInterpolated 只能在查询根上使用,并且都可以防止SQL注入。

    var query = await _context.Set<User>().FromSqlInterpolated($"select * from user where Id={"1395392302788120576"}").ToListAsync();Console.WriteLine(JsonConvert.SerializeObject(query));

生成SQL

      select * from user where Id=@p0
[{"Account":"张三","PassWord":"123456","CreateTime":"2021-05-20T22:53:44.778101","IsValid":false,"Id":"1395392302788120576"}]

3.4.3 限制

  • SQL查询必须返回实体类型的所有属性的数据。

  • 结果集中的列明必须与属性映射到的列名称匹配。

  • SQL查询不能包含关联数据, 但是,在许多情况下你可以在查询后面紧跟着使用 Include 方法以返回关联数据(请参阅包含关联数据)。

参考文档:https://docs.microsoft.com/zh-cn/ef/core/querying/raw-sql

3.5 复杂查询

数据如下:

用户表(user)

image.png

用户成绩表(score)

image.png

描述:包含三个用户,其中两个用户在成绩表都有语文和数学的数据。

3.5.1 内连接

内连接:分为隐式内连接和显式内连接(写法不同,结果相同)

3.5.1.1 Linq查询表达式

显式内连接:join-in-on拼接
    var list = (from u in _context.Usersjoin sc in _context.Scores on u.Id equals sc.UserIdwhere sc.CourseName == "语文"select new{u.Account,u.PassWord,sc.CourseName,sc.Grade}).ToList();Console.WriteLine(JsonConvert.SerializeObject(list));

记得引用:System.Linq  否则提示:未找到源类型“DbSet”的查询模式的实现,未找到join

生成SQL

      SELECT `u`.`Account`, `u`.`PassWord`, `s`.`CourseName`, `s`.`Grade`FROM `user` AS `u`INNER JOIN `score` AS `s` ON `u`.`Id` = `s`.`UserId`WHERE `s`.`CourseName` = '语文'

结果

image.png
隐式内连接:多个from并联拼接
    var list = (from u in _context.Usersfrom sc in _context.Scoreswhere u.Id == sc.UserId && sc.CourseName == "语文"select new{u.Account,u.PassWord,sc.CourseName,sc.Grade}).ToList();Console.WriteLine(JsonConvert.SerializeObject(list));

生成SQL

      SELECT `u`.`Account`, `u`.`PassWord`, `s`.`CourseName`, `s`.`Grade`FROM `user` AS `u`CROSS JOIN `score` AS `s`WHERE (`u`.`Id` = `s`.`UserId`) AND (`s`.`CourseName` = '语文')

结果

image.png

3.5.1.2 Linq标准查询运算符

    var list = _context.Users.Where(t => t.Account != null).Join(_context.Scores.Where(sc => sc.CourseName == "语文"), u => u.Id, sc => sc.UserId, (u, sc) => new{u.Account,u.PassWord,sc.CourseName,sc.Grade}).ToList();Console.WriteLine(JsonConvert.SerializeObject(list));

生成SQL

      # 不加查询课程SELECT `u`.`Account`, `u`.`PassWord`, `s`.`CourseName`, `s`.`Grade`FROM `user` AS `u`INNER JOIN `score` AS `s` ON `u`.`Id` = `s`.`UserId`# 查询课程SELECT `u`.`Account`, `u`.`PassWord`, `t`.`CourseName`, `t`.`Grade`FROM `user` AS `u`INNER JOIN (SELECT `s`.`CourseName`, `s`.`Grade`, `s`.`UserId`FROM `score` AS `s`WHERE `s`.`CourseName` = '语文') AS `t` ON `u`.`Id` = `t`.`UserId`

结果

image.png

3.5.2 外连接

外连接join后必须有into,然后可以加上XX.DefaultIfEmpty(),表示对于引用类型将返回null,而对于值类型则返回0。对于结构体类型,则会根据其成员类型将它们相应地初始化为null(引用类型)或0(值类型),

如果仅需要统计右表的个数或者其它属性,可以省略XX.DefaultIfEmpty, 但如果需要点出来右表的字段,则不能省。

3.5.2.1 linq实现

查询所有用户对应的班级,因为用户和成绩一对多,所以会出现多条数据

    var list = (from u in _context.Usersjoin sc in _context.Scores on u.Id equals sc.UserIdinto ulistfrom sco in ulist.DefaultIfEmpty()where u.Account != null //这个条件只是展示如何添加条件select new{UserId = u.Id,Account = u.Account,sco.CourseName}).ToList();Console.WriteLine(JsonConvert.SerializeObject(list));

生成SQL

      SELECT `u`.`Id` AS `UserId`, `u`.`Account`, `s`.`CourseName`FROM `user` AS `u`LEFT JOIN `score` AS `s` ON `u`.`Id` = `s`.`UserId`

结果

image.png

如果要查询成绩,应该这么写,上面那个写法会直接报错, Nullable object must have a value

image.png

3.5.3 GroupJoin

GroupJoin操作符常应用于返回“主键对象-外键对象集合”形式的查询,例如“用户信息-此用户下所有科目成绩”

    var list = _context.Users.Where(t => t.Account != null).GroupJoin(_context.Scores, u => u.Id, sc => sc.UserId, (u, sc) => new{u.Account,u.PassWord,Scores = sc}).ToList();Console.WriteLine(JsonConvert.SerializeObject(list));

该代码会提示错误,原因如:https://docs.microsoft.com/zh-cn/ef/core/querying/client-eval

3.5.4 GrouBy

分组操作 根据用户分组,求科目数

    var list = (from sc in _context.Scoresgroup sc by sc.UserIdinto gselect new{g.Key,Count = g.Count()}).ToList();Console.WriteLine(JsonConvert.SerializeObject(list));var list2 = _context.Scores.GroupBy(sc => sc.UserId).Select(t => new{t.Key,Count = t.Count()}).ToList();Console.WriteLine(JsonConvert.SerializeObject(list2));

生成SQL

info: Microsoft.EntityFrameworkCore.Database.Command[20101]Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']SELECT `s`.`UserId` AS `Key`, COUNT(*) AS `Count`FROM `score` AS `s`GROUP BY `s`.`UserId`
[{"Key":"1395392302788120576","Count":2},{"Key":"1395392303090110464","Count":2}]
info: Microsoft.EntityFrameworkCore.Database.Command[20101]Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']SELECT `s`.`UserId` AS `Key`, COUNT(*) AS `Count`FROM `score` AS `s`GROUP BY `s`.`UserId`
[{"Key":"1395392302788120576","Count":2},{"Key":"1395392303090110464","Count":2}]

4. 添加

4.1 基础添加

    _context.Movie.Add(movie);// orawait _context.Movie.AddRangeAsync(movies)await _context.SaveChangesAsync();

4.2 已经设置自增键的插入

先关闭自增然后插入数据后再开启自增

        db.Database.OpenConnection();db.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [T_RoleInfor] ON");var r2 = new T_RoleInfor(){id = 123,roleName = "管理员",roleDescription = "我是管理员"};db.Add(r2);int count2 = db.SaveChanges();db.Database.ExecuteSqlCommand("SET ID   ENTITY_INSERT [T_RoleInfor] OFF");

4.3 通过SQL添加

    var strSql2 = "INSERT INTO `userinfo`(`Id`, `Account`, `PassWord`) VALUES (@id, @account, @password);";var parameter2 = new MySqlParameter[] {new MySqlParameter("@id","22"),new MySqlParameter("@account","2222"),new MySqlParameter("@password","22222")};var flg = db.Database.ExecuteSqlRaw(strSql2, parameter2);// 调用存储过程int n = db.Database.ExecuteSqlCommand("DoSome @id", para);//参数化查询

2.x使用ExecuteSqlCommand,3.x使用ExecuteSqlRaw方法

5. 修改

    var  movie = await _context.Movie.FirstOrDefaultAsync(m => m.ID == id);movie.Name="李思";await _context.SaveChangesAsync();  

6. 删除

    var movie = await _context.Movie.FirstOrDefaultAsync(m => m.ID == id);_context.Movie.Remove(movie);await _context.SaveChangesAsync();

7. 参考文档

官方例子:https://docs.microsoft.com/zh-cn/ef/core/dbcontext-configuration/

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

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

相关文章

一堂儿童科学实验课引起的思考:数学和化学有什么关系?

全世界只有3.14 % 的人关注了数据与算法之美前段时间&#xff0c;我带侄子上了一堂化学课&#xff0c;回来之后&#xff0c;他一直意犹未尽找我的聊化学的事&#xff0c;期间他也问了身为数学专业的我一个交叉问题&#xff1a;叔&#xff0c;「数学」和「化学」有啥关系&#x…

使用 KubernetesClient 操作 kubernetes

使用 KubernetesClient 操作 kubernetesIntro我们的应用都是部署在 Kubernetes 上的&#xff0c;我们有一个服务内部有一层 MemoryCache&#xff0c;之前会依赖 Redis 的 Pub/Sub 来做缓存的更新&#xff0c;而 Redis 的 Pub/Sub 是一种不可靠的更新机制&#xff0c;容易发生消…

cent os重置mysql,linux mysql 能登陆不能修改用户(cent os 6.2)解决思路

linux mysql 能登陆不能修改用户(cent os 6.2)[root3mao /]# select user,host,password from mysql.userbash: syntax error near unexpected token from[root3mao /]# mysql -u rootWelcome to the MySQL monitor. Commands end with ; or /g.Your MySQL connection id is 4S…

本、硕、博到底有什么区别?清华教授的“兔子理论”让你快速弄懂

全世界只有3.14 % 的人关注了数据与算法之美前段时间&#xff0c;有人问到卢sir一个问题——“本、硕、博之间到底有什么区别&#xff1f;”曾经就有一位清华大学教授就讨论过这个问题&#xff0c;让我们来看看这位清华教授是如何看待本、硕、博区别的吧。作者 | 阎学通教授清华…

迁移SVN注意事项及操作方法

最近公司要迁移SVN到新服务器&#xff0c;虽说现在GIT貌似更胜一筹&#xff0c;但是相信用svn的公司还是不在少数&#xff0c;就花了点时间把自己迁移的过程整理了一下。 文档中也许还有不足之处&#xff0c;有问题的话&#xff0c;大家可以告诉我&#xff0c;我会在第一时间修…

重磅!微软发布新一代 Teams 开发工具 —— Teams Toolkit!不止VS Code extension!

今天凌晨&#xff08;北京时间 2021 年 5 月 26 日&#xff09;&#xff0c;在一年一度的 Build 大会上&#xff0c;微软正式发布了新一代的 Teams 开发工具 —— Teams Toolkit。截止到 2021 年 4 月份&#xff0c;Microsoft Teams 的日活用户已经达到了惊人的1.45亿&#xff…

UML实践----用例图、顺序图、状态图、类图、包图、协作图

http://www.uml.org.cn/oobject/200901203.asp UML实践----用例图、顺序图、状态图、类图、包图、协作图 2009-01-20 作者&#xff1a;Randy Miller 来源&#xff1a;网络 面向对象的问题的处理的关键是建模问题。建模可以把在复杂世界的许多重要的细节给抽象出。许多建模工具封…

“六级”题公布,觉得WebAPI简单的,勿进!

大型业务为什么需要深入WebAPI?众所周知&#xff0c;开发健壮的&#xff0c;稳定的&#xff0c;高度扩展性的业务程序&#xff0c;必须要有好的业务框架程序。就好比宝马X5和东风雪铁龙&#xff0c;如果大家体验过两车性能&#xff0c;都知道&#xff0c;宝马X5的性能甩东风雪…

hdu 2896 病毒侵袭

http://acm.hdu.edu.cn/showproblem.php?pid2896 AC自动机的简单题。。。忘记关debug了&#xff0c;wa了一次。。。囧&#xff01; View Code 1 #include <cstdio>2 #include <cstring>3 #include <algorithm>4 #include <set>5 #include <cstdli…

一件有趣的事:我用 Python 爬了爬自己的微信朋友

全世界只有3.14 % 的人关注了数据与算法之美最近几天干啥都不来劲&#xff0c;昨晚偶然了解到Python里的itchat包&#xff0c;它已经完成了wechat的个人账号API接口&#xff0c;使爬取个人微信信息更加方便。鉴于自己很早之前就想知道诸如自己微信好友性别比例都来自哪个城市之…

ML.NET Cookbook:(4)如何调试实验或预览管道?

大多数ML.NET数据操作都是延迟执行的&#xff1a;声明时&#xff0c;操作符不会立即处理数据&#xff0c;而是验证该操作是否可行。执行被推迟到实际请求输出数据为止。这意味着架构不匹配将在声明时抛出&#xff0c;但是直到执行时才抛出数据错误。延迟计算是数据库系统的一种…

数学本是非常有趣的,只是教科书呈现的方式太死板

数学是基础学科&#xff0c;是打开科学大门的钥匙。数学能力决定着一个人的科技创新能力&#xff0c;而科技创新能力决定着一个孩子未来的竞争力。数学也是一门不断累积的学问&#xff0c;学习数学也是一个渐进的过程&#xff0c;要是基础的概念不理解&#xff0c;基础学习得不…

oracle期间平均成本,小李飞刀系列之Oracle EBS期间平均成本(PAC)--生产成本计算(四)制造费用设置及成本计算...

在上两篇文章中介绍了资源的设置及其成本计算&#xff0c;本篇文章将介绍与资源关联非常紧密的制造费用的设置及成本计算。1. 制造费用设置图 1. 制造费用主设置界面制造费用主设置界面如图1所示&#xff0c;成本要素选择”制造费用”&#xff0c;并设置制造费用的名称、说明、…

通过Dapr实现一个简单的基于.net的微服务电商系统(十二)——istio+dapr构建多运行时服务网格...

多运行时是一个非常新的概念。在 2020 年&#xff0c;Bilgin Ibryam 提出了 Multi-Runtime&#xff08;多运行时&#xff09;的理念&#xff0c;对基于 Sidecar 模式的各种产品形态进行了实践总结和理论升华。那到底什么是多运行时呢&#xff1f;首先还是得从分布式应用的四大类…

如何把文件压缩变成一张图片?

全世界只有3.14 % 的人关注了数据与算法之美先准备好三个文件。图片、压缩包、批处理文件。然后编辑bat文件。压缩命令代码是&#xff1a;copy /b 图片.jpg压缩包.rar 最后输出文件名.jpg例如&#xff1a;copy /b A.jpgtest.rar B.jpg 注意空格。保存之后执行bat批处理文件。执…

.NET程序崩溃了怎么抓 Dump ? 我总结了三种方案

一&#xff1a;背景 1. 讲故事最近几天接到了几个crash的求助&#xff0c;可能这几个朋友没玩过怎么去生成dump&#xff0c;只能手把手教&#xff0c;感觉也不是一个办法&#xff0c;所以有必要总结一下&#xff0c;后续再有朋友咨询的话&#xff0c;我就可以把这篇文章丢过去了…

敏捷软件开发之结对编程

2019独角兽企业重金招聘Python工程师标准>>> 说明 【作为推荐的最佳实践&#xff0c;结对编程早已为人们熟知&#xff0c;并且也是所有XP实践中争议最大的一个】 结对编程技术是一个非常简单和直观的概念&#xff1a;两位程序员肩并肩地坐在同一台电脑前合作完成同一…

Build 2021 :正式发布.NET 6 Preview4

微软在不断推进.NET 6的可用性&#xff0c;昨晚的Build 2021大会上发布了Preview4&#xff0c; 这是一个很大的版本更新&#xff0c;带来大量的功能&#xff0c;以及接近最终的产品交付质量&#xff0c;不过&#xff0c;这并不意味着可以在生产环境使用了&#xff0c;正式发布R…

程序员与代码的几种关系,每种都会被我们鄙视

全世界只有3.14 % 的人关注了数据与算法之美程序员很大部分时间都在和代码打交道&#xff0c;所以程序员和代码之间的关系&#xff0c;在很多常人看来&#xff0c;是无法理解的&#xff0c;下面我们就来聊聊。找到你仅仅是为了将你消灭掉在程序员的世界里面&#xff0c;一个词语…

.NET 6 Preview 4 已发布,ASP.NET Core 更新内容

原文&#xff1a;bit.ly/3wFqDy9作者&#xff1a;Daniel译者&#xff1a;王亮.NET 6 预览版 4 现已发布&#xff0c;其中包括对 ASP.NET Core 的许多新改进。下面是此次预览版中 ASP.NET Core 的更新内容&#xff1a;引入最小 API异步流HTTP 日志中间件新项目中使用 Kestrel 作…