当前位置:   article > 正文

.Net -- EF Core详解_efcore

efcore

                               目录                                   

1. EF Core简介

2. Demo运行环境

3. 创建Prism项目 & 类库

4. EF Core -- DBFirst

5. EF Core -- CodeFirst

6. EF Core -- 增删改查

6.1 查询

6.2 插入

6.3 更新

6.4 删除

7. EF Core -- 批量更新

7.1 使用EFCore.BulkExtensions操作Postgresql

7.1.1 Bulk相关(一条操作一个事务,均是传入实体)

7.1.2 Batch相关(按条件)

7.1.3 事务

7.2 使用 Zack.EFCore.Batch.MySQL.Pomelo_NET6 操作Mysql

8. 其他

8.1  VS2022安装PrismTemplatePack

8.2  使用Zack.EFCore.Batch.MySQL.Pomelo_NET6 操作mysql时报错

8.3  插入数据报错

8.4  使用 await dbFContext.BulkReadAsync(students),查询不到数据?

9. github地址

10. 参考


1. EF Core简介

Entity Framework (EF) Core 是轻量化、可扩展、开源和跨平台版的常用 Entity Framework 数据访问技术。

EF Core 可用作对象关系映射程序 (O/RM),这可以实现以下两点:

  • 使 .NET 开发人员能够使用 .NET 对象处理数据库。
  • 无需再像通常那样编写大部分数据访问代码。

EF Core 支持多个数据库引擎,请参阅数据库提供程序了解详细信息。

Code First :先编写 C# 实体类,EF Core 会根据实体类之间的关系创建数据库;

Database First :先设计和创建数据库,EF Core 根据数据库的表结构生成 C# 实体类。

2. Demo运行环境

IDE -- VS2022

框架 --  .Net 6.0

数据访问 --  EF Core 6.0.1

UI -- WPF --Prism框架

数据库 -- Mysql、Postgresql

3. 创建Prism项目 & 类库

创建Prism项目,修改目标框架为.Net 6.0

 再创建两个类库,分别对应DBFirst/CodeFirst,为EFCore_Test添加这两个项目引用

 

4. EF Core -- DBFirst

使用NuGet安装下图几个包

 DBFirst采用Postgresql。使用pgAdmin 4创建数据库EFCoreDB,三个表student、course、

choose_course

 根据已有数据库生成实体:

将EFCore_DBFirst该项目设置为启动项目,进入程序包控制台,如图:

 输入如下指令,Scaffold-DbContext指令详情

Scaffold-DbContext -Connection "Server=127.0.0.1;Port=5432;Database=EFCoreDB;User Id=postgres;Password=1;" -Provider Npgsql.EntityFrameworkCore.PostgreSQL -Context DBFContext

运行成功后,生成如下实体类

 

context中配置数据库连接时,使用明文产生此警告,可改为使用配置文档

添加配置文档appsettings.json

  1. {
  2. "ConnectionStrings": {
  3. "NpgsqlDbConn_DBFirst": "Server=127.0.0.1;Port=5432;Database=EFCoreDB;User Id=postgres;Password=1;",
  4. "MysqlDbConn_CodeFirst": "Server=127.0.0.1;Port=3306;Database=EFCoreCode;User Id=root;Password=hirosedb;"
  5. }
  6. }

调用

  1. protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
  2. {
  3. if (!optionsBuilder.IsConfigured)
  4. {
  5. IConfiguration config = new ConfigurationBuilder()
  6. .SetBasePath(Directory.GetCurrentDirectory())
  7. .AddJsonFile("appsettings.json")
  8. .Build();
  9. string ConnectStr = config.GetConnectionString("NpgsqlDbConn_DBFirst");
  10. optionsBuilder.UseNpgsql(ConnectStr);
  11. }
  12. }

5. EF Core -- CodeFirst

CodeFirst使用Mysql,Nuget安装如下包

 新建实体类:Book、Comment,使用特性实体与数据库对应

  1. using System.ComponentModel.DataAnnotations;
  2. using System.ComponentModel.DataAnnotations.Schema;
  3. namespace EFCore_CodeFirst
  4. {
  5. [Table("Book")] //表名
  6. public class Book
  7. {
  8. [Key] //主键
  9. [Column("Id")] //列名
  10. [DatabaseGenerated(DatabaseGeneratedOption.Identity)] //主键自增
  11. public int Id { get; set; }
  12. [Column("Title")]
  13. public string? Title { get; set; }
  14. [Column("Price")]
  15. public double? Price { get; set; }
  16. [Column("PubTime")]
  17. public DateTime? PubTime { get; set; }=DateTime.Now;
  18. [Column("AuthorName")]
  19. public string? AuthorName { get; set; }
  20. }
  21. }
  1. [Table("Comment")]
  2. public class Comment
  3. {
  4. [Key]
  5. [Column("Id")]
  6. [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  7. public int Id { get; set; }
  8. [Column("Title")]
  9. public string? Title { get; set; }
  10. [Column("CreatedDate")]
  11. public DateTime CreatedDate { get; set; }=DateTime.Now;
  12. [Column("CommentStr")]
  13. public string? CommentStr { get; set; }
  14. }

创建context类,继承DbContext

  1. using Microsoft.EntityFrameworkCore;
  2. using Microsoft.Extensions.Configuration;
  3. namespace EFCore_CodeFirst
  4. {
  5. public class CodeFContext : DbContext
  6. {
  7. //定义实体 EFcore默认追踪
  8. public DbSet<Book> Books { get; set; } = null!;
  9. public DbSet<Comment> Comments { get; set; } = null!;
  10. private string ConnectStr=null!;
  11. protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
  12. {
  13. if (!optionsBuilder.IsConfigured)
  14. {
  15. IConfiguration config = new ConfigurationBuilder()
  16. .SetBasePath(Directory.GetCurrentDirectory())
  17. .AddJsonFile("appsettings.json")
  18. .Build();
  19. ConnectStr = config.GetConnectionString("MysqlDbConn_CodeFirst");
  20. optionsBuilder.UseMySql(ConnectStr, ServerVersion.AutoDetect(ConnectStr));
  21. }
  22. }
  23. protected override void OnModelCreating(ModelBuilder modelBuilder)
  24. {
  25. base.OnModelCreating(modelBuilder);
  26. }
  27. }
  28. }

由实体生成数据库,将EFCore_CodeFirst设为启动项目,调用指令add-migration "变量";

会生成如下文件

调用指令Update-Database ,更新数据库

使用Navicat查看数据库,生成成功

6. EF Core -- 增删改查

先new一个context实例,通过绑定跟踪的DbSet实体,实现数据操作

private CodeFContext codeFContext= new CodeFContext();

6.1 查询

  1. private List<Book> _books;
  2. public List<Book> Books
  3. {
  4. get => _books;
  5. set => SetProperty (ref _books, value);
  6. }
  7. //查询Book表所有数据
  8. Books = codeFContext.Books.ToList();
  9. //条件查询,linq操作
  10. Books = codeFContext.Books.Where(x => x.Id > 3).ToList();

6.2 插入

  1. private async void InsertData()
  2. {
  3. var books=new List<Book>() {
  4. new Book() { Title ="追风筝的人"},
  5. new Book() { Title ="霍乱时期的爱情"}
  6. };
  7. //修改DbSet
  8. codeFContext.Books.AddRange(books);
  9. //再save更改
  10. await codeFContext.SaveChangesAsync();
  11. }

6.3 更新

  1. private async void UpdateData()
  2. {
  3. //需要先查询
  4. var books = codeFContext.Books.Where(x => x.Title == "追风筝的人");
  5. //再对查询到的数据进行修改
  6. foreach (var item in books)
  7. {
  8. item.Title = "放学后";
  9. }
  10. //再save更改
  11. await codeFContext.SaveChangesAsync();
  12. }

6.4 删除

  1. private async void DeleteData()
  2. {
  3. //先Linq查询
  4. var books= codeFContext.Books.Where(x => x.Id>5);
  5. //从实体中删除数据
  6. codeFContext.Books.RemoveRange(books);
  7. //再save更改
  8. await codeFContext.SaveChangesAsync();
  9. }

7. EF Core -- 批量更新

EF 目前不提供用于执行批量更新的 API.

7.1 使用EFCore.BulkExtensions操作Postgresql

 7.1.1 Bulk相关(一条操作一个事务,均是传入实体)

  1. //查询
  2. List<Student> students =new List<Student>();
  3. await dbFContext.BulkReadAsync(students);
  4. //插入
  5. var students = new List<Student>(){
  6. new Student() {Id=1, Name = "AA" ,StuNum="2010"},
  7. new Student() {Id=2, Name = "BB" ,StuNum="2011"},
  8. new Student() {Id=3, Name = "CC",StuNum="2012" }};
  9. await dbFContext.BulkInsertAsync(students);
  10. //删除
  11. var stus = dbFContext.Students;
  12. await dbFContext.BulkDeleteAsync(stus.ToList());
  13. //更新
  14. var stus = dbFContext.Students.ToList();
  15. foreach (var item in stus)
  16. {
  17. item.Name += "QQQ";
  18. }
  19. await dbFContext.BulkUpdateAsync(stus);

7.1.2 Batch相关(按条件)

  1. //删除
  2. await dbFContext.Students.Where(x=>x.Name=="BB").BatchDeleteAsync();
  3. //更新(改成新数据)
  4. await dbFContext.Students.Where(x => x.StuNum == "2222").BatchUpdateAsync(new Student() {StuNum="2233" });
  5. //更新(基于原数据)
  6. await dbFContext.Students.Where(x => x.StuNum == "2233").BatchUpdateAsync(x=>new Student() { StuNum =x.StuNum+ "444" });

7.1.3 事务

  1. //Bulk相关(一条操作一个事务,均是传入实体)
  2. //直接使用这些操作时,每个操作都是独立的事务,并且会自动提交。
  3. //如果我们需要在单个过程中执行多个操作,则应使用显式事务
  4. public async void TransactionTest()
  5. {
  6. using (var transaction= dbFContext.Database.BeginTransaction())
  7. {
  8. try
  9. {
  10. var students = new List<Student>(){
  11. new Student() {Id=6, Name = "DD" ,StuNum="2044"},
  12. new Student() {Id=7, Name = "EE" ,StuNum="2055"}};
  13. await dbFContext.BulkInsertAsync(students);
  14. await dbFContext.Students.Where(x => x.StuNum == "2044").BatchUpdateAsync(new Student() { Name = "DDEEF" });
  15. transaction.Commit();
  16. }
  17. catch (Exception ex )
  18. {
  19. //using包裹不需要手写rollback,报错会自动回滚
  20. Console.WriteLine(ex.Message);
  21. }
  22. }
  23. }

7.2 使用 Zack.EFCore.Batch.MySQL.Pomelo_NET6 操作Mysql

  1. //添加配置
  2. protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
  3. {
  4. if (!optionsBuilder.IsConfigured)
  5. {
  6. optionsBuilder.UseBatchEF_MySQLPomelo();
  7. }
  8. }
  9. //批量删除,
  10. await codeFContext.DeleteRangeAsync<Book>(x=>x.Id>5);
  11. //批量更新,条件,设置更新的列和值,执行
  12. await codeFContext.BatchUpdate<Book>()
  13. .Where(x => x.Title == "放学后")
  14. .Set(x=>x.Title,x=>x.Title+"Test")
  15. .Set(x=>x.Price,x=>20)
  16. .ExecuteAsync();
  17. //批量删除和批量更新都支持通过Take()、Skip()来实现部分删除和部分更新
  18. // Take(3) 代表选取3个 ,如果满足条件的不足3个 那就有几个选几个 可以一个都没有,超过的话只选顺序前 3 个
  19. await codeFContext.Books.Where(x=>x.Id>5).Take(3).DeleteRangeAsync(codeFContext);
  20. //Skip(3) 代表跳过3个 ,如果满足条件的不足3个 那就有几个选几个 跳过几个,超过的话只跳过顺序的前 3 个
  21. await codeFContext.BatchUpdate<Book>()
  22. .Where(x => x.Title == "放学后")
  23. .Set(x => x.Title, x => x.Title + "Test")
  24. .Set(x => x.Price, x => 20)
  25. .Skip(3)
  26. .ExecuteAsync();
  27. //批量插入
  28. var books=new List<Book>() {
  29. new Book() { Title ="追风筝的人"},
  30. new Book() { Title ="霍乱时期的爱情"}
  31. };
  32. await codeFContext.BulkInsertAsync(books);

8. 其他

 8.1  VS2022安装PrismTemplatePack

        VS2022扩展中搜不到Prism模板,安装包在github中有。

 8.2  使用Zack.EFCore.Batch.MySQL.Pomelo_NET6 操作mysql时报错

        插入数据   await codeFContext.BulkInsertAsync(books),报如下错误

  解决:在json配置文件中的,连接字符串添加AllowLoadLocalInfile=true

8.3  插入数据报错

 

解决:查看全局系统变量 'local_infile' 的值,将其set为on,如下图。自此,插入语句可正常执行

 

8.4 使用 await dbFContext.BulkReadAsync(students),查询不到数据?

     求解

9. github地址

KilterW/EFCore_Test: Basic use of EFCore (github.com)

10. 参考

入门 - EF Core | Microsoft Docs

EF Core中高效批量删除、更新数据的Zack.EFCore.Batch发布三个新特性 - 知乎 (zhihu.com)

EFcore使用EFCore.BulkExtensions 批量增加、删除、修改 – MENG (nipoo.net)

        

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/666152
推荐阅读
相关标签
  

闽ICP备14008679号