如何使用 FreeSql 无缝接替 EF Core ?

news/2024/4/24 20:21:07/文章来源:https://blog.csdn.net/ChaITSimpleLove/article/details/129223443

如何使用 FreeSql 无缝接替 EF Core,并实现数据表的 CRUD 操作

  • 项目说明
  • DB & 数据表结构
    • DB & 数据表创建
    • 数据表 User 实体模型创建
  • 使用 EF Core 实现 User 表新增用户信息
    • 添加 EF Core 相关的 nuget 包
    • 编写 EF Core 操作 User 表的 CRUD 代码
  • FreeSql 使用 DbContext 接替 EF Core
    • 单例对象构造器 SingletonConstructor
    • 使用 SingletonConstructor 构建 IFreeSql
    • 反射解析 DatabaseFacade
      • EF Core 中 DbContext 官方定义
      • EF Core 中 DatabaseFacade 官方定义
      • 反射解析对象 DatabaseFacade
  • 测试 orm 两种模式下的操作
    • 添加 User 用户信息
    • FreeSql 查询 User 用户信息
  • 总结

Gradual evolution

项目说明

  • 实现目标:使用 FreeSql 无缝接替 EF Core,并实现数据表的 CRUD 操作;

接下来我们先回顾下 EF Core 中如何实现数据表的 CRUD 操作,在操作之前我们先把数据库和相关表结构准备好。

DB & 数据表结构

  • 数据库实例名称:Test
  • 数据表结构:User

此处为了方便演示,创建一个简单的 User 表,数据结构如下:

字段说明
Id主键,用户ID
Name用户姓名

DB & 数据表创建

创建数据库实例 TestUser 表,执行如下 sql 脚本:

USE master;  
GO  -- 创建 Test
CREATE DATABASE Test  
ON   
( NAME = Test_dat,  FILENAME = 'D:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\testdat.mdf',  SIZE = 10,  MAXSIZE = 50,  FILEGROWTH = 5 )  
LOG ON  
( NAME = Test_log,  FILENAME = 'D:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\testlog.ldf',  SIZE = 5MB,  MAXSIZE = 25MB,  FILEGROWTH = 5MB );  
GOCREATE TABLE Test.dbo.[User] (Id varchar(36) NOT NULL primary key,Name varchar(20) NOT NULL
);
EXEC Test.sys.sp_addextendedproperty 'MS_Description', N'用户信息', 'schema', N'dbo', 'table', N'User';
GO

执行上面 sql 脚本创建数据库失败时,可以先执行如下 sql 脚本,然后在继续执行上面步骤。

-- 关闭数据库连接并删除数据库
ALTER DATABASE Test SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE Test;

除了上面常规的 mssql 配置,开发环境为了方便快捷,还可以使用 Docker 运行 mssql 镜像(mcr.microsoft.com/mssql/server),此处我是配置的 Docker 环境(这里不做详细介绍,感兴趣的小伙伴自行查看资料):

docker-mssql

到这里我们就把基本的开发环境准备好了,接下来就是新建项目相关环节的操作。

数据表 User 实体模型创建

依据上面的 User 表结构,在(新建)项目 Jeff.Mes.EntityFrameworkCore 中添加 C# 模型类:

using System.ComponentModel.DataAnnotations.Schema;namespace Jeff.Mes.EntityFrameworkCore;/// <summary>
/// 用户信息表
/// </summary>
[Table("User")]
public class User
{/// <summary>/// 主键,用户ID /// </summary>public string Id { get; set; }/// <summary>/// 用户姓名/// </summary>public string Name { get; set; }
}

使用 EF Core 实现 User 表新增用户信息

上面我们准备好 Test 数据库、User 表和 C# 实体模型结构 后,接下来准备编写 EF Core 相应的操作代码。

添加 EF Core 相关的 nuget 包

说明:此处环境使用的 SqlServer 数据库,其他类型的数据库需添加相应的 nuget 包。

接着我们继续在上面新建的项目【Jeff.Mes.EntityFrameworkCore】中改造,添加 nuget 包:

  • Microsoft.EntityFrameworkCore.SqlServer
NuGet\Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 6.0.14

efcore.sqlserver

编写 EF Core 操作 User 表的 CRUD 代码

项目【Jeff.Mes.EntityFrameworkCore】中添加 FreeSqlNuget 包:

  • FreeSql.Provider.SqlServer
NuGet\Install-Package FreeSql.Provider.SqlServer -Version 3.2.687

FreeSql.Provider.SqlServer

在项目【Jeff.Mes.EntityFrameworkCore】中新建 TestContext 类,继承 DbContext,实现如下:

using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations.Schema;namespace Jeff.Mes.EntityFrameworkCore;/// <summary>
/// Test 数据库上下文对象
/// </summary>
public class TestContext : DbContext
{public TestContext() { }/// <summary>/// 用户信息表/// </summary>public virtual DbSet<User> User { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){if (!optionsBuilder.IsConfigured){// db 连接字符串,其中符号 “***” 代表数据库访问密码string dbConnString = "Data Source=.;Initial Catalog=Test;Persist Security Info=True;User ID=sa;Password=***";optionsBuilder.UseSqlServer(dbConnString);}}/// <summary>/// 【EF Core 模式】添加用户测试/// </summary>/// <returns></returns>public async Task<int> AddUserAsync(){using (var dbContext = new TestContext()){var guid = Guid.NewGuid().ToString();var user = new User{Id = guid,Name = $"efcore-{guid.Substring(0, 5)}"};dbContext.Add(user);return await dbContext.SaveChangesAsync();}}// 注意对比下面的,【FreeSql 模式】添加用户测试
}

上面操作 User 表的 CRUD 代码,为了简化此处只写 AddUserAsync 添加操作,其他代码就不在详细介绍。

FreeSql 使用 DbContext 接替 EF Core

Entity Framework(简称 EF) 中创建模型后,应用程序所交互的主要类是 System.Data.Entity.DbContext(通常称为 上下文类 )。默认情况下,上下文管理与数据库的连接。

单例对象构造器 SingletonConstructor

单例对象构造器 SingletonConstructor 代码如下:

namespace Jeff.Mes.Common;/// <summary>
/// 单例对象构造器
/// </summary>
/// <typeparam name="T"></typeparam>
public class SingletonConstructor<T> where T : class, new()
{private static T? _Instance;private readonly static object _lockObj = new();/// <summary>/// 获取单例对象的实例/// </summary>/// <returns></returns>public static T GetInstance(){if (_Instance != null) return _Instance;lock (_lockObj){if (_Instance == null){var item = System.Activator.CreateInstance<T>();System.Threading.Interlocked.Exchange(ref _Instance, item);}}return _Instance;}
}

使用 SingletonConstructor 构建 IFreeSql

新建 FreeSqlHelper.cs 文件,使 FreeSqlHelper 类继承自 SingletonConstructor 单例构造器,代码示例如下:

using System.Collections.Concurrent;
using FreeSql;
using Jeff.Mes.Common;namespace Jeff.Mes.DbHelper;/// <summary>
/// 【Singleton 单例模式】构建 freesql 对象
/// </summary>
public sealed class FreeSqlHelper : SingletonConstructor<FreeSqlHelper>
{//连接字符串作为 key,存储构建的 IFreeSql 对象的字典集合private readonly static ConcurrentDictionary<string, IFreeSql> _FreeDic = new();#region 构建 freesql 对象public IFreeSql? FreeBuilder(string dbType, string connStr){if (string.IsNullOrWhiteSpace(dbType) || string.IsNullOrWhiteSpace(connStr)){return default;}bool isOk = _FreeDic.TryGetValue(connStr, out IFreeSql? fsql);if (isOk){return fsql;}DataType dataType;string myDbType = dbType.Contains('.') ? dbType.Substring(dbType.LastIndexOf('.') + 1) : dbType;switch (myDbType.ToLower()){case "mysql":dataType = DataType.MySql;break;default:dataType = DataType.SqlServer;break;}return FreeBuilder(dataType, connStr);}public IFreeSql? FreeBuilder(DataType dbType, string connStr){if (string.IsNullOrWhiteSpace(connStr)){return default;}/*bool hasKey = _FreeDic.ContainsKey(connStr);if (hasKey){return _FreeDic[connStr];}*/bool isOk = _FreeDic.TryGetValue(connStr, out IFreeSql? fsql);if (isOk){return fsql;}fsql = new FreeSqlBuilder().UseConnectionString(dbType, connStr).UseAutoSyncStructure(false) //自动同步实体结构到数据库.Build(); //请务必定义成 Singleton 单例模式 bool isAdd = _FreeDic.TryAdd(connStr, fsql);if (isAdd){return fsql;}else{fsql.Dispose();return _FreeDic[connStr];}}public (bool isOk, IFreeSql? fsql) GetFreeSql(DataType dbType, string connStr){bool isOk = _FreeDic.TryGetValue(connStr, out IFreeSql? fsql);if (!isOk){fsql = FreeBuilder(dbType, connStr);isOk = fsql != null;}return (isOk, fsql ?? default);}#endregion
}

使用 FreeSqlHelper 对象构建 IFreeSql,如下代码:

 IFreeSql fsql = FreeSqlHelper.GetInstance().FreeBuilder(dbType, connStr);

上面环节我们就准备好了 IFreeSql 对象的构建,万事俱备,只欠东风(下面我们解析解析 DbContext 获取有效信息);

反射解析 DatabaseFacade

在反射解析 DbContext 对象之前,我们先回顾下相关概念定义和类库基本信息。

EF Core 中 DbContext 官方定义

  • Microsoft.EntityFrameworkCore.DbContext

上面我简单的介绍了 DbContextEF Core数据库连接对象,接下来我们看下官方定义:

  • 命名空间:Microsoft.EntityFrameworkCore
  • 程序集:Microsoft.EntityFrameworkCore.dll
  • Nuget 包:Microsoft.EntityFrameworkCore v7.0.0

DbContext 实例表示与数据库的会话,可用于查询和保存实体的实例。 DbContext 是工作单元和存储库模式的组合。

public class DbContext : IAsyncDisposable, 
IDisposable, Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<IServiceProvider>, 
Microsoft.EntityFrameworkCore.Internal.IDbContextDependencies, 
Microsoft.EntityFrameworkCore.Internal.IDbContextPoolable, 
Microsoft.EntityFrameworkCore.Internal.IDbSetCache

关于 DbContext 更多信息,请查看 =》https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.entityframeworkcore.dbcontext?view=efcore-7.0

EF Core 中 DatabaseFacade 官方定义

  • Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade

DatabaseFacade 类定义如下:

  • 命名空间:Microsoft.EntityFrameworkCore.Infrastructure
  • 程序集:Microsoft.EntityFrameworkCore.dll
  • Nuget 包:Microsoft.EntityFrameworkCore v7.0.0

提供对上下文的数据库相关信息和操作的访问。 此类的实例通常是从 Database 中获取的,它不是在应用程序代码中直接构造的。

public class DatabaseFacade : 
Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<IServiceProvider>, 
Microsoft.EntityFrameworkCore.Infrastructure.IResettableService, 
Microsoft.EntityFrameworkCore.Storage.IDatabaseFacadeDependenciesAccessor

关于 DatabaseFacade 更多信息,请查看 =》https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.entityframeworkcore.infrastructure.databasefacade?view=efcore-7.0

反射解析对象 DatabaseFacade

  • Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade

添加反射解析 DatabaseFacade 对象的代码:

/// <summary>
/// 根据对象实例和属性名称获得属性值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <param name="property"></param>
/// <returns></returns>
public static T? GetProperty<T>(this object obj, string property)
{var result = default(T);try{var t = obj.GetType();var propertyObj = t.GetProperty(property)?.GetValue(obj, null);result = (T?)propertyObj.ChangeType(typeof(T));return result;}catch(Exception ex){throw ex;}
}/// <summary>
/// 类型转换
/// </summary>
/// <param name="value"></param>
/// <param name="type"></param>
/// <returns></returns>
public static object? ChangeType(this object? value, Type type)
{if (value == null && type.IsGenericType) return Activator.CreateInstance(type);if (value == null) return null;if (type == value.GetType()) return value;if (type.IsEnum){if (value is string valEnum) return Enum.Parse(type, valEnum);else return Enum.ToObject(type, value);}if (!type.IsInterface && type.IsGenericType){Type innerType = type.GetGenericArguments()[0];object? innerValue = ChangeType(value, innerType);return Activator.CreateInstance(type, new object?[] { innerValue });}if (value is string valGuid && type == typeof(Guid)) return new Guid(valGuid);if (value is string valVersion && type == typeof(Version)) return new Version(valVersion);if (value is Guid && type == typeof(string)) return value.ToString();if (value is not IConvertible) return value;if (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>))){var underlyingType = Nullable.GetUnderlyingType(type);type = underlyingType ?? type;} // end ifreturn Convert.ChangeType(value, type);
}

继续在 TestContext.cs 类中添加如下代码:

/// <summary>
/// 【FreeSql 模式】添加用户测试
/// </summary>
/// <returns></returns>
public async Task<int> FreeSqlAddUserAsync()
{using (var dbContext = new TestContext()){var (myDbContext, fsql) = GetDbContext(dbContext);var guid = Guid.NewGuid().ToString();var user = new User{Id = guid,Name = $"fsql-{guid.Substring(0, 5)}"};// fsql.Insert(user).AsTable("User").ExecuteAffrowsAsync();return await fsql.Insert(user).ExecuteAffrowsAsync();}
}/// <summary>
/// 反射获取信息,并构建 FreeSql
/// </summary>
/// <param name="dbContext"></param>
/// <returns></returns>
public (DbContext dbContext, IFreeSql fsql) GetDbContext(DbContext dbContext)
{/*((EQuality.Framework.Dal.EFDbContext)_IDbContext).ConnStr((Microsoft.EntityFrameworkCore.DbContext)ss).Database.ProviderName*///-	Database	// {Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade}	// Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacadevar dbFacade = dbContext.GetProperty<DatabaseFacade>("Database");string dbType = dbFacade.ProviderName; // db 类型string connStr = dbContext.Database.GetConnectionString(); // 获取 db 连接字符串IFreeSql fsql = FreeSqlHelper.GetInstance().FreeBuilder(dbType, connStr); // 单例构造器构建 IFreeSql 对象 return (dbContext, fsql);
}

此处项目【Jeff.Mes.EntityFrameworkCore】中 TestContext.cs 类已经完成两种 orm 模式下新增 User 信息的操作,分别是:

  • AddUserAsync,【EF Core 模式】添加用户测试;
  • FreeSqlAddUserAsync,【FreeSql 模式】添加用户测试;

到这里我们就可以使用 FreeSql 无缝替换 EF Core 的操作,同时也保留了 EF Core 模式的玩法,小伙伴们又可以继续愉快的玩耍了哟。

测试 orm 两种模式下的操作

添加 User 用户信息

新增控制台项目【Jeff.Mes.EntityFrameworkCore.Test】,项目引用【Jeff.Mes.EntityFrameworkCore】,添加如下代码:

namespace Jeff.Mes.EntityFrameworkCore.Test;internal class Program
{static async Task Main(string[] args){Console.WriteLine("Hello, EF Core & FreeSQL!");var test = new TestContext();int rcount1 = await test.AddUserAsync();string info1 = rcount1 > 0 ? "User 信息添加成功" : "User 信息添加失败";Console.WriteLine($"efcore 模式:{info1}");int rcount2 = await test.FreeSqlAddUserAsync();string info2 = rcount2 > 0 ? "User 信息添加成功" : "User 信息添加失败";Console.WriteLine($"fsql 模式:{info2}");Console.ReadKey();}
}

使用 vs 【工具 => 连接到数据库】测试数据库连接是否能正常通信访问,测试如下:

vs 连接数据库

启动控制台,执行代码,输出如下信息:

Hello, EF Core & FreeSQL!
efcore 模式:User 信息添加成功
fsql 模式:User 信息添加成功

控制台测试

使用数据库客户端工具 DBeaver 查看:

user表数据

FreeSql 查询 User 用户信息

使用 FreeSQL 查询 User 表信息:

/// <summary>
/// 【FreeSql 模式】查询用户信息
/// </summary>
/// <returns></returns>
public async Task<List<User>> FreeSqlGetUserAsync()
{using (var dbContext = new TestContext()){var (myDbContext, fsql) = GetDbContext(dbContext);return await fsql.Select<User>().ToListAsync();}
}

控制台 Main 函数中调用 FreeSqlGetUserAsync 方法:

fsql 查询 user 信息

关于 FreeSql 更多信息,请查看相关文档

  • FreeSql 官方文档,https://freesql.net/
  • FreeSql 博客文档,https://www.cnblogs.com/FreeSql/p/11531300.html

总结

在使用 EF Core 作为默认的 ORM 工具操作数据库时,项目中我们或许只能接触到 DbContext 对象,没法直接获取 db 数据库连接信息,假如有小伙伴想接入 FreeSQL 继续使用熟悉的模式,那该怎么办呢?此时我们可以这样操作,为了不影响原有项目结构的操作,又想接入 FreeSQL 的小伙伴们,通过上面的方式我们就可以使用 FreeSQL 无缝替换 EF Core

其实接入 FreeSQL 的方式很简单,只需具备两点条件即可,首先就是 有效的 db 连接字符串dbContext.Database.GetConnectionString()】,其次就是获取对应的 数据库类型dbFacade.ProviderName】。

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

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

相关文章

AI_Papers周刊:第三期

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 2023.02.20—2023.02.26 文摘词云 Top Papers Subjects: cs.CL 1.LLaMA: Open and Efficient Foundation Language Models 标题&#xff1a;LLaMA&#xff1a;开放高效的基础语言模型 作者&#…

zookeeper集群的搭建,菜鸟升级大神必看

一、下载安装zookeeperhttp://archive.apache.org/dist/zookeeper/下载最新版本2.8.1http://archive.apache.org/dist/zookeeper/zookeeper-3.8.1/二、上传安装包到服务器上并且解压&#xff0c;重命名tar -zxvf apache-zookeeper-3.8.1-bin.tar.gzmv apache-zookeeper-3.8.1-b…

Python安装教程(附带安装包)

首先&#xff0c;打开python安装包的下载地址&#xff0c;https://www.python.org/downloads/&#xff0c;会有些慢 点击downloads中的windows 左侧是稳定的版本&#xff0c;我这边下的是3.8的&#xff0c;不想去官网下载的可以直接用我下载的这个3.8版本&#xff0c;https://…

WebGPU学习(4)---使用 UniformBuffer

接下来让我们使用 UniformBuffer。UniformBuffer 是一个只读内存区域&#xff0c;可以在着色器上访问。 这次&#xff0c;我们将传递给着色器的矩阵存储在 UniformBuffer 中。演示示例 1.在顶点着色器中的 UniformBuffer 这次我们在顶点着色器里定义一个名为Uniforms的新结构体…

《爆肝整理》保姆级系列教程python接口自动化(二十三)--unittest断言——上(详解)

简介 在测试用例中&#xff0c;执行完测试用例后&#xff0c;最后一步是判断测试结果是 pass 还是 fail&#xff0c;自动化测试脚本里面一般把这种生成测试结果的方法称为断言&#xff08;assert&#xff09;。用 unittest 组件测试用例的时候&#xff0c;断言的方法还是很多的…

Zebec社区上线ZIP-2(地平线升级行动)提案

此前&#xff0c;Zebec社区在上线了投票治理系统Zebec Node后&#xff0c;曾上线了首个提案ZIP-1&#xff0c;对Nautilus Chain的推出进行了投票&#xff0c;作为Zebec Chain上线前的“先行链”&#xff0c;该链得到了社区用户的欢迎&#xff0c;投通过票的比例高达98.3%。而Na…

JSP网上书店系统用myeclipse定制开发mysql数据库B/S模式java编程计算机网页

一、源码特点 JSP 网上书店系统 是一套完善的系统源码&#xff0c;对理解JSP java 编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。研究的基本内容是基于网上书店系 统&#xff0c;使用JSP作为页面开发工具。Web服务的运…

【Python工具篇】Anaconda中安装python2和python3以及在pycharm中使用

背景&#xff1a;已经安装好anaconda、python3、pycharm&#xff0c;因为项目使用的是python2语法&#xff0c;所以需要在anaconda中安装python2&#xff0c;并在pycharm中使用&#xff0c;下面给出步骤。 1. 打开cmd或者是Anaconda Prompt。 下面是anaconda prompt. 2. 查…

【Java学习】初识Java

JavaSEJava初识1. Java简介2.Java环境的安装与配置3. 开发第一个Java程序Java初识 学前疑问&#xff1a;&#xff08;带着疑问去学习&#xff0c;在学习中自行探索答案&#xff09; Java是什么&#xff1f;能做什么&#xff1f;发展前景如何&#xff1f;需要学习哪些内容&…

mysql数据库表的创建与查看

mysql数据库表的创建与查看 一、mysql查看 查看所有数据库 show databases切换数据库 use 数据库名查看该数据库下所有的表名 show tables查看表的结构 desc 表名二、mysq创建 创建数据库 create database 数据库名;创建数据库设置编码 drop database if EXISTS dbname; creat…

终端软件架构说

目录 零&#xff1a;前言 一&#xff0c;基于服务的架构 二&#xff0c;基于多进程多线程的架构 三&#xff0c;以数据为中心的架构 四&#xff0c;类Android的分层架构设计 五&#xff0c;总结 零&#xff1a;前言 谈到架构&#xff0c;可能大家的第一感觉是信息系统的…

redis数据结构的底层实现

文章目录一.引言二.redis的特点三.Redis的数据结构a.字符串b.hashc.listd.sete.zset(有序集合)一.引言 redis是一个开源的使用C语言编写、支持网络、可基于内存亦可持久化的日志型、key-value的NoSQL数据库。 通常使用redis作为缓存中间件来降低数据库的压力&#xff0c;除此…

STC单片机启动看门狗定时器介绍和使用

STC单片机启动看门狗定时器介绍 ✨这里以STC8系列为例。 📑看门狗复位(WDT_CONTR) WDT_FLAG:看门狗溢出标志 看门狗发生溢出时,硬件自动将此位置 1,需要软件清零。EN_WDT:看门狗使能位 0:对单片机无影响 1:启动看门狗定时器。 注意:看门狗定时器可使用软件方式启动,…

CXL互联标准简介及相关资料

毕设是实现CXL的type3扩展内存设备&#xff0c;因为CXL技术非常新&#xff0c;2019年推出&#xff0c;本专栏也是记录CXL的相关知识与一些浅薄的理解 文章目录CXL出现的背景CXL是什么其他互联总线介绍CXL胜出的原因CXL内容简介包含三种协议 CXL.io/cache/memory支持三种设备类型…

Reids实战—黑马点评(三)秒杀篇

Reids实战—黑马点评&#xff08;三&#xff09;秒杀篇 来自黑马的redis课程的笔记 【黑马程序员Redis入门到实战教程&#xff0c;深度透析redis底层原理redis分布式锁企业解决方案黑马点评实战项目】 目录Reids实战—黑马点评&#xff08;三&#xff09;秒杀篇一、全局唯一I…

DevOps实战50讲-(1)彻底理解DevOps

持续坚持原创输出&#xff0c;点击蓝字关注我吧软件质量保障:所寫即所思&#xff5c;一个阿里质量人对测试的所感所悟。浅谈软件开发流程软件开发流程是从需求分析、设计、编码、测试到上线等一系列环节的步骤和活动。通常来说&#xff0c;软件开发流程可以分为以下几个阶段&am…

Python 多进程多线程线程池进程池协程

目录 一、线程与进程很简单的介绍 1.1 线程与进程的区别 二、多进程Process 2.1 多进程与多线程的区别 2.2 多进程为啥要使用队列 2.3 控制进程运行顺序 2.3.1 join &#xff0c; 2.3.1 daemon 守护进程 2.4 进程id 2.5 进程 存活状态is_alive() 2.5 实现自定义多…

计算机图形学:liang算法和Cyrus-Beck算法

其中Cyrus-Beck算法呢&#xff0c;是计算一根直线一个多边形的交线段&#xff1b;liang算法是Cyrus的一个特例&#xff0c;即多边形刚好是矩形&#xff1b;先看看Cyrus算法的思路【从别的博客找的图片】&#xff1a;这很容易理解&#xff0c;点积>0时就可能中内部嘛&#xf…

Pyinstaller 打包EXE(七) 百篇文章学PyQT

本文章是百篇文章学PyQT6的第七篇&#xff0c;本文讲述如何使用Pyinstaller打包UI界面和代码&#xff0c;将程序打包成EXE来更为方便的进行部署&#xff0c;在写博客和学习的过程中会遇到很多问题&#xff0c;例如&#xff1a;PyQT6在网上很多博客都是PyQT5、或者PyQT4大部分都…

Amazon S3 服务15岁生日快乐!

2021年3月14日&#xff0c;作为第一个发布的服务&#xff0c;Amazon S3 服务15周岁啦&#xff01;在中国文化里&#xff0c;15岁是个临界点&#xff0c;是从“舞勺之年”到“舞象之年”的过渡。相信对于 Amazon S3 和其他的云服务15周岁也将是其迎接更加美好未来的全新起点。亚…