赞
踩
7.1 使用EFCore.BulkExtensions操作Postgresql
7.2 使用 Zack.EFCore.Batch.MySQL.Pomelo_NET6 操作Mysql
8.2 使用Zack.EFCore.Batch.MySQL.Pomelo_NET6 操作mysql时报错
8.4 使用 await dbFContext.BulkReadAsync(students),查询不到数据?
Entity Framework (EF) Core 是轻量化、可扩展、开源和跨平台版的常用 Entity Framework 数据访问技术。
EF Core 可用作对象关系映射程序 (O/RM),这可以实现以下两点:
EF Core 支持多个数据库引擎,请参阅数据库提供程序了解详细信息。
Code First :先编写 C# 实体类,EF Core 会根据实体类之间的关系创建数据库;
Database First :先设计和创建数据库,EF Core 根据数据库的表结构生成 C# 实体类。
IDE -- VS2022
框架 -- .Net 6.0
数据访问 -- EF Core 6.0.1
UI -- WPF --Prism框架
数据库 -- Mysql、Postgresql
创建Prism项目,修改目标框架为.Net 6.0
再创建两个类库,分别对应DBFirst/CodeFirst,为EFCore_Test添加这两个项目引用
使用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
- {
- "ConnectionStrings": {
- "NpgsqlDbConn_DBFirst": "Server=127.0.0.1;Port=5432;Database=EFCoreDB;User Id=postgres;Password=1;",
- "MysqlDbConn_CodeFirst": "Server=127.0.0.1;Port=3306;Database=EFCoreCode;User Id=root;Password=hirosedb;"
- }
- }
调用
- protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
- {
- if (!optionsBuilder.IsConfigured)
- {
- IConfiguration config = new ConfigurationBuilder()
- .SetBasePath(Directory.GetCurrentDirectory())
- .AddJsonFile("appsettings.json")
- .Build();
- string ConnectStr = config.GetConnectionString("NpgsqlDbConn_DBFirst");
- optionsBuilder.UseNpgsql(ConnectStr);
- }
- }
CodeFirst使用Mysql,Nuget安装如下包
新建实体类:Book、Comment,使用特性实体与数据库对应
- using System.ComponentModel.DataAnnotations;
- using System.ComponentModel.DataAnnotations.Schema;
-
- namespace EFCore_CodeFirst
- {
- [Table("Book")] //表名
- public class Book
- {
- [Key] //主键
- [Column("Id")] //列名
- [DatabaseGenerated(DatabaseGeneratedOption.Identity)] //主键自增
- public int Id { get; set; }
- [Column("Title")]
- public string? Title { get; set; }
- [Column("Price")]
- public double? Price { get; set; }
- [Column("PubTime")]
- public DateTime? PubTime { get; set; }=DateTime.Now;
- [Column("AuthorName")]
- public string? AuthorName { get; set; }
- }
- }
- [Table("Comment")]
- public class Comment
- {
- [Key]
- [Column("Id")]
- [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
- public int Id { get; set; }
- [Column("Title")]
- public string? Title { get; set; }
- [Column("CreatedDate")]
- public DateTime CreatedDate { get; set; }=DateTime.Now;
- [Column("CommentStr")]
- public string? CommentStr { get; set; }
- }
创建context类,继承DbContext
- using Microsoft.EntityFrameworkCore;
- using Microsoft.Extensions.Configuration;
-
- namespace EFCore_CodeFirst
- {
- public class CodeFContext : DbContext
- {
- //定义实体 EFcore默认追踪
- public DbSet<Book> Books { get; set; } = null!;
- public DbSet<Comment> Comments { get; set; } = null!;
- private string ConnectStr=null!;
-
- protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
- {
- if (!optionsBuilder.IsConfigured)
- {
- IConfiguration config = new ConfigurationBuilder()
- .SetBasePath(Directory.GetCurrentDirectory())
- .AddJsonFile("appsettings.json")
- .Build();
- ConnectStr = config.GetConnectionString("MysqlDbConn_CodeFirst");
- optionsBuilder.UseMySql(ConnectStr, ServerVersion.AutoDetect(ConnectStr));
- }
- }
-
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- base.OnModelCreating(modelBuilder);
- }
- }
- }
由实体生成数据库,将EFCore_CodeFirst设为启动项目,调用指令add-migration "变量";
会生成如下文件
调用指令Update-Database ,更新数据库
使用Navicat查看数据库,生成成功
先new一个context实例,通过绑定跟踪的DbSet实体,实现数据操作
private CodeFContext codeFContext= new CodeFContext();
- private List<Book> _books;
-
- public List<Book> Books
- {
- get => _books;
- set => SetProperty (ref _books, value);
- }
- //查询Book表所有数据
- Books = codeFContext.Books.ToList();
- //条件查询,linq操作
- Books = codeFContext.Books.Where(x => x.Id > 3).ToList();
- private async void InsertData()
- {
- var books=new List<Book>() {
- new Book() { Title ="追风筝的人"},
- new Book() { Title ="霍乱时期的爱情"}
- };
- //修改DbSet
- codeFContext.Books.AddRange(books);
- //再save更改
- await codeFContext.SaveChangesAsync();
- }
- private async void UpdateData()
- {
- //需要先查询
- var books = codeFContext.Books.Where(x => x.Title == "追风筝的人");
- //再对查询到的数据进行修改
- foreach (var item in books)
- {
- item.Title = "放学后";
- }
- //再save更改
- await codeFContext.SaveChangesAsync();
-
- }
- private async void DeleteData()
- {
- //先Linq查询
- var books= codeFContext.Books.Where(x => x.Id>5);
- //从实体中删除数据
- codeFContext.Books.RemoveRange(books);
- //再save更改
- await codeFContext.SaveChangesAsync();
- }
EF 目前不提供用于执行批量更新的 API.
- //查询
- List<Student> students =new List<Student>();
- await dbFContext.BulkReadAsync(students);
- //插入
- var students = new List<Student>(){
- new Student() {Id=1, Name = "AA" ,StuNum="2010"},
- new Student() {Id=2, Name = "BB" ,StuNum="2011"},
- new Student() {Id=3, Name = "CC",StuNum="2012" }};
- await dbFContext.BulkInsertAsync(students);
- //删除
- var stus = dbFContext.Students;
- await dbFContext.BulkDeleteAsync(stus.ToList());
- //更新
- var stus = dbFContext.Students.ToList();
- foreach (var item in stus)
- {
- item.Name += "QQQ";
- }
- await dbFContext.BulkUpdateAsync(stus);
- //删除
- await dbFContext.Students.Where(x=>x.Name=="BB").BatchDeleteAsync();
- //更新(改成新数据)
- await dbFContext.Students.Where(x => x.StuNum == "2222").BatchUpdateAsync(new Student() {StuNum="2233" });
- //更新(基于原数据)
- await dbFContext.Students.Where(x => x.StuNum == "2233").BatchUpdateAsync(x=>new Student() { StuNum =x.StuNum+ "444" });
-
- //Bulk相关(一条操作一个事务,均是传入实体)
- //直接使用这些操作时,每个操作都是独立的事务,并且会自动提交。
- //如果我们需要在单个过程中执行多个操作,则应使用显式事务
- public async void TransactionTest()
- {
- using (var transaction= dbFContext.Database.BeginTransaction())
- {
- try
- {
- var students = new List<Student>(){
- new Student() {Id=6, Name = "DD" ,StuNum="2044"},
- new Student() {Id=7, Name = "EE" ,StuNum="2055"}};
- await dbFContext.BulkInsertAsync(students);
- await dbFContext.Students.Where(x => x.StuNum == "2044").BatchUpdateAsync(new Student() { Name = "DDEEF" });
- transaction.Commit();
- }
- catch (Exception ex )
- {
- //using包裹不需要手写rollback,报错会自动回滚
- Console.WriteLine(ex.Message);
- }
-
- }
- }
- //添加配置
- protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
- {
- if (!optionsBuilder.IsConfigured)
- {
- optionsBuilder.UseBatchEF_MySQLPomelo();
- }
- }
-
-
- //批量删除,
- await codeFContext.DeleteRangeAsync<Book>(x=>x.Id>5);
- //批量更新,条件,设置更新的列和值,执行
- await codeFContext.BatchUpdate<Book>()
- .Where(x => x.Title == "放学后")
- .Set(x=>x.Title,x=>x.Title+"Test")
- .Set(x=>x.Price,x=>20)
- .ExecuteAsync();
- //批量删除和批量更新都支持通过Take()、Skip()来实现部分删除和部分更新
- // Take(3) 代表选取3个 ,如果满足条件的不足3个 那就有几个选几个 可以一个都没有,超过的话只选顺序前 3 个
- await codeFContext.Books.Where(x=>x.Id>5).Take(3).DeleteRangeAsync(codeFContext);
- //Skip(3) 代表跳过3个 ,如果满足条件的不足3个 那就有几个选几个 跳过几个,超过的话只跳过顺序的前 3 个
- await codeFContext.BatchUpdate<Book>()
- .Where(x => x.Title == "放学后")
- .Set(x => x.Title, x => x.Title + "Test")
- .Set(x => x.Price, x => 20)
- .Skip(3)
- .ExecuteAsync();
- //批量插入
- var books=new List<Book>() {
- new Book() { Title ="追风筝的人"},
- new Book() { Title ="霍乱时期的爱情"}
- };
- await codeFContext.BulkInsertAsync(books);
VS2022扩展中搜不到Prism模板,安装包在github中有。
插入数据 await codeFContext.BulkInsertAsync(books),报如下错误
解决:在json配置文件中的,连接字符串添加AllowLoadLocalInfile=true
解决:查看全局系统变量 'local_infile' 的值,将其set为on,如下图。自此,插入语句可正常执行
求解
KilterW/EFCore_Test: Basic use of EFCore (github.com)
EF Core中高效批量删除、更新数据的Zack.EFCore.Batch发布三个新特性 - 知乎 (zhihu.com)
EFcore使用EFCore.BulkExtensions 批量增加、删除、修改 – MENG (nipoo.net)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。