.NET Core MongoDB数据仓储和工作单元模式实操

前言

  上一章节我们主要讲解了MongoDB数据仓储和工作单元模式的封装,这一章节主要讲的是MongoDB用户管理相关操作实操。如:获取所有用户信息、获取用户分页数据、通过用户ID获取对应用户信息、添加用户信息、事务添加用户信息、用户信息修改、用户信息删除等实战教程。

MongoDB从入门到实战的相关教程

MongoDB从入门到实战之MongoDB简介👉

MongoDB从入门到实战之MongoDB快速入门👉

MongoDB从入门到实战之Docker快速安装MongoDB👉

MongoDB从入门到实战之MongoDB工作常用操作命令👉

MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(1)-后端项目框架搭建👉

MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(2)-Swagger框架集成👉

MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(3)-系统数据集合设计👉

MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(4)-MongoDB数据仓储和工作单元模式封装👉

MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(5)-MongoDB数据仓储和工作单元模式实操👉

YyFlight.ToDoList项目源码地址

欢迎各位看官老爷review,有帮助的别忘了给我个Star哦💖!!!

GitHub地址:GitHub - YSGStudyHards/YyFlight.ToDoList: 【.NET8 MongoDB 待办清单系统】.NET8 MongoDB从入门到实战基础教程,该项目后端使用的是.NET8、前端页面使用Blazor、使用MongoDB存储数据,更多相关内容大家可以看目录中的MongoDB从入门到实战的相关教程。该系列教程可作为.NET Core入门项目进行学习,感兴趣的小伙伴可以关注博主和我一起学习共同进步。

MongoRepository地址:https://github.com/YSGStudyHards/YyFlight.ToDoList/tree/main/Repository/Repository

MongoDB事务使用前提说明

参阅MongoDB的事务👉

说明:

MongoDB单机服务器不支持事务【使用MongoDB事务会报错:Standalone servers do not support transactions】,只有在集群情况下才支持事务,因为博主接下来都是在单机环境下操作,所以无法来演示Mongo事务操作,但是方法都已经是封装好了的,大家可以自己搭建集群实操。

原因:

MongoDB在使用分布式事务时需要进行多节点之间的协调和通信,而单机环境下无法实现这样的分布式协调和通信机制。但是,在MongoDB部署为一个集群(cluster)后,将多个计算机连接为一个整体,通过协调和通信机制实现了分布式事务的正常使用。从数据一致性和可靠性的角度来看,在分布式系统中实现事务处理是至关重要的。而在单机环境下不支持事务,只有在集群情况下才支持事务的设计方式是为了保证数据一致性和可靠性,并且也符合分布式系统的设计思想。

创建EntityBase公共类

一个公共的具有相同特性和行为的基类。

    public class EntityBase{/// <summary>/// 主键Id/// </summary>[BsonId][BsonRepresentation(BsonType.ObjectId)]public string Id { get; set; }/// <summary>/// 创建时间/// </summary>public DateTime CreateDate { get; set; }/// <summary>/// 更新时间/// </summary>public DateTime UpdateDate { get; set; }}

添加UserInfo用户表实体映射模型

    [Table("yyflight_todolist_user")]public class UserInfo : EntityBase{/// <summary>/// 登录账号/// </summary>public string UserName { get; set; }/// <summary>/// 登录密码/// </summary>public string Password { get; set; }/// <summary>/// 用户昵称/// </summary>public string NickName { get; set; }/// <summary>/// 用户头像/// </summary>public string HeadPortrait { get; set; }/// <summary>/// 用户邮箱/// </summary>public string Email { get; set; }/// <summary>/// 用户状态(0冻结,1正常,2注销)/// </summary>public int Status { get; set; }}

在前面类中,Id属性中的特性的作用:

  • 需要用于将通用语言运行时(CLR)对象映射到MongoDB集合。
  • 用[BsonId]进行注释,使该属性成为文档的主键。
  • 用[BsonRepresentation(BsonType.ObjectId)]进行注释,以允许以字符串类型而不是ObjectId结构传递参数。Mongo处理从字符串到ObjectId的转换。没有此特性序列化时会有如下异常提示:

System.FormatException: An error occurred while deserializing the Id property of class Repository.Domain.User.UserInfo: Cannot deserialize a 'String' from BsonType 'ObjectId'.

知识拓展MongoDB ObjectId类型概述:

每次插入一条数据系统都会自动插入一个_id键,键值不可以重复,它可以是任何类型的,也可以手动的插入,默认情况下它的数据类型是ObjectId,由于MongoDB在设计之初就是用作分布式数据库,所以使用ObjectId可以避免不同数据库中_id的重复(如果使用自增的方式在分布式系统中就会出现重复的_id的值)。
ObjectId使用12字节的存储空间,每个字节可以存储两个十六进制数字,所以一共可以存储24个十六进制数字组成的字符串,在这24个字符串中,前8位表示时间戳,接下来6位是一个机器码,接下来4位表示进程id,最后6位表示计数器。

MongoDB 采用 ObjectId 来表示主键的类型,数据库中每个文档都拥有一个_id 字段表示主键,_id 的生成规则如下:

其中包括4-byte Unix 时间戳,3-byte 机器 ID,2-byte 进程 ID,3-byte 计数器(初始化随机)

601e2b6b  a3203c  c89f   2d31aa↑        ↑       ↑       ↑时间戳    机器码   进程ID   随机数 

创建用户Repository

创建用户IUserRepository接口

    public interface IUserRepository : IMongoRepository<UserInfo>{}

创建用户UserRepository类

    public class UserRepository : MongoBaseRepository<UserInfo>, IUserRepository{public UserRepository(IMongoContext context) : base(context){}}

创建用户管理业务代码

创建IUserOperationExampleServices接口

    public interface IUserOperationExampleServices{/// <summary>/// 获取所有用户信息/// </summary>/// <returns></returns>Task<IEnumerable<UserInfo>> GetAllUserInfos();/// <summary>/// 用户分页数据获取/// </summary>/// <param name="userInfoByPageListReq">userInfoByPageListReq</param>/// <returns></returns>Task<IEnumerable<UserInfo>> GetUserInfoByPageList(UserInfoByPageListReq userInfoByPageListReq);/// <summary>/// 通过用户ID获取对应用户信息/// </summary>/// <param name="id">id</param>/// <returns></returns>Task<UserInfo> GetUserInfoById(string id);/// <summary>/// 添加用户信息/// </summary>/// <param name="userInfo">userInfo</param>/// <returns></returns>Task<UserInfo> AddUserInfo(UserInfoReq userInfo);/// <summary>/// 事务添加用户信息/// </summary>/// <param name="userInfo">userInfo</param>/// <returns></returns>Task<UserInfo> AddUserInfoTransactions(UserInfoReq userInfo);/// <summary>/// 用户信息修改/// </summary>/// <param name="id">id</param>/// <param name="userInfo">userInfo</param>/// <returns></returns>Task<UserInfo> UpdateUserInfo(string id, UserInfoReq userInfo);/// <summary>/// 用户信息删除/// </summary>/// <param name="id">id</param>/// <returns></returns>Task<bool> Delete(string id);}

创建UserOperationExampleServices类

    public class UserOperationExampleServices : IUserOperationExampleServices{private readonly IUnitOfWork _unitOfWork;private readonly IUserRepository _userRepository;/// <summary>/// 依赖注入/// </summary>/// <param name="unitOfWork">unitOfWork</param>/// <param name="userRepository">userRepository</param>public UserOperationExampleServices(IUnitOfWork unitOfWork, IUserRepository userRepository){_unitOfWork = unitOfWork;_userRepository = userRepository;}/// <summary>/// 获取所有用户信息/// </summary>/// <returns></returns>public async Task<IEnumerable<UserInfo>> GetAllUserInfos(){var getAllUserInfos = await _userRepository.GetAllAsync();return getAllUserInfos;}/// <summary>/// 用户分页数据获取/// </summary>/// <param name="userInfoByPageListReq">userInfoByPageListReq</param>/// <returns></returns>public async Task<IEnumerable<UserInfo>> GetUserInfoByPageList(UserInfoByPageListReq request){//创建查询条件构造器FilterDefinitionBuilder<UserInfo> buildFilter = Builders<UserInfo>.Filter;FilterDefinition<UserInfo> filter = buildFilter.Empty;SortDefinition<UserInfo> sort = Builders<UserInfo>.Sort.Ascending(m => m.CreateDate);if (!string.IsNullOrEmpty(request.NickName)){filter = buildFilter.Eq(m => m.NickName, request.NickName);}if (!string.IsNullOrEmpty(request.Id)){filter = buildFilter.Eq(m => m.Id, request.Id);}var list = await _userRepository.FindListByPageAsync(filter, request.PageIndex, request.PageSize, Array.Empty<string>(), sort);return list;}/// <summary>/// 通过用户ID获取对应用户信息/// </summary>/// <param name="id">id</param>/// <returns></returns>public async Task<UserInfo> GetUserInfoById(string id){var getUserInfo = await _userRepository.GetByIdAsync(id);return getUserInfo;}/// <summary>/// 添加用户信息/// </summary>/// <param name="userInfo">userInfo</param>/// <returns></returns>public async Task<UserInfo> AddUserInfo(UserInfoReq userInfo){var addUserInfo = new UserInfo(){Id = ObjectId.GenerateNewId().ToString(),UserName = userInfo.UserName,Email = userInfo.Email,NickName = userInfo.NickName,Password = MD5Helper.MDString(userInfo.Password),Status = 1,HeadPortrait = userInfo.HeadPortrait,CreateDate = DateTime.Now,UpdateDate = DateTime.Now,};await _userRepository.AddAsync(addUserInfo);var queryUserInfo = await _userRepository.GetByIdAsync(addUserInfo.Id);return queryUserInfo;}/// <summary>/// 事务添加用户信息/// </summary>/// <param name="userInfo">userInfo</param>/// <returns></returns>public async Task<UserInfo> AddUserInfoTransactions(UserInfoReq userInfo){using var session = await _unitOfWork.InitTransaction();var addUserInfo = new UserInfo(){Id = ObjectId.GenerateNewId().ToString(),UserName = userInfo.UserName,Email = userInfo.Email,NickName = userInfo.NickName,Password = MD5Helper.MDString(userInfo.Password),Status = 1,HeadPortrait = userInfo.HeadPortrait,CreateDate = DateTime.Now,UpdateDate = DateTime.Now,};await _userRepository.AddTransactionsAsync(session, addUserInfo);//查不到任何信息var queryUserInfo = await _userRepository.GetByIdAsync(addUserInfo.Id);//提交新增用户信息操作await _unitOfWork.Commit(session);//UserInfo只有在提交后才会被添加queryUserInfo = await _userRepository.GetByIdAsync(addUserInfo.Id);return queryUserInfo;}/// <summary>/// 用户信息修改/// </summary>/// <param name="id">id</param>/// <param name="userInfo">userInfo</param>/// <returns></returns>public async Task<UserInfo> UpdateUserInfo(string id, UserInfoReq userInfo){#region 指定字段和条件修改//修改条件var list = new List<FilterDefinition<UserInfo>>{Builders<UserInfo>.Filter.Eq("_id", new ObjectId(id))};var filter = Builders<UserInfo>.Filter.And(list);//指定要修改的字段内容//参考文章:https://chsakell.gitbook.io/mongodb-csharp-docs/crud-basics/update-documentsvar updateDefinition = Builders<UserInfo>.Update.Set(u => u.HeadPortrait, userInfo.HeadPortrait).Set(u => u.NickName, userInfo.NickName).Set(u => u.Status, userInfo.Status);await _userRepository.UpdateAsync(filter, updateDefinition);#endregion#region 指定对象异步修改一条数据//var updateUserInfo = new UserInfo//{//    UserName = userInfo.UserName,//    Password = MD5Helper.MDString(userInfo.Password),//    Status = 1,//    HeadPortrait = userInfo.HeadPortrait,//    Email = userInfo.Email,//    NickName = userInfo.NickName,//    UpdateDate = DateTime.Now,//};//await _userRepository.UpdateAsync(updateUserInfo, id);#endregion#region 数据批量修改示例1.批量修改的条件(把创建时间CreateDate为近五日的用户状态更改为0)//var time = DateTime.Now;//var list = new List<FilterDefinition<UserInfo>>();//list.Add(Builders<UserInfo>.Filter.Gt("CreateDate", time));//大于当前时间//list.Add(Builders<UserInfo>.Filter.Lt("CreateDate", time.AddDays(5)));//小于当前时间+5day//var filter = Builders<UserInfo>.Filter.And(list);2.要修改的字段内容//var dic = new Dictionary<string, string>//{//    { "Status", "0" }//};3.批量修改//await _userRepository.UpdateManayAsync(dic, filter);#endregionreturn await _userRepository.GetByIdAsync(id);}/// <summary>/// 用户信息删除/// </summary>/// <param name="id"></param>/// <returns></returns>public async Task<bool> Delete(string id){await _userRepository.DeleteAsync(id);var testUserInfo = await _userRepository.GetByIdAsync(id);return testUserInfo == null;}}

UserOperationExample控制创建

    /// <summary>/// MongoDB用户管理操作示例/// </summary>[ApiController][Produces("application/json")][Route("api/[controller]/[action]")]public class UserOperationExampleController : ControllerBase{private readonly IUserOperationExampleServices _userOperationExampleServices;/// <summary>/// 依赖注入/// </summary>/// <param name="userOperationExampleServices">userOperationExampleServices</param>public UserOperationExampleController(IUserOperationExampleServices userOperationExampleServices){_userOperationExampleServices = userOperationExampleServices;}/// <summary>/// 获取所有用户信息/// </summary>/// <returns></returns>[HttpGet]public async Task<ActionResult<IEnumerable<UserInfo>>> GetAllUserInfos(){var userInfos = await _userOperationExampleServices.GetAllUserInfos();return Ok(userInfos);}/// <summary>/// 获取用户分页数据/// </summary>/// <param name="userInfoByPageListReq">userInfoByPageListReq</param>/// <returns></returns>[HttpPost]public async Task<ActionResult<IEnumerable<UserInfo>>> GetUserInfoByPageList([FromBody] UserInfoByPageListReq userInfoByPageListReq){var getUserInfoByPageList = await _userOperationExampleServices.GetUserInfoByPageList(userInfoByPageListReq);return Ok(getUserInfoByPageList);}/// <summary>/// 通过用户ID获取对应用户信息/// </summary>/// <param name="id">id</param>/// <returns></returns>[HttpGet("{id}")]public async Task<ActionResult<UserInfo>> GetUserInfoById(string id){var userInfo = await _userOperationExampleServices.GetUserInfoById(id);return Ok(userInfo);}/// <summary>/// 添加用户信息/// </summary>/// <param name="userInfo">userInfo</param>/// <returns></returns>[HttpPost]public async Task<ActionResult<UserInfo>> AddUserInfo([FromBody] UserInfoReq userInfo){var addUserInfo = await _userOperationExampleServices.AddUserInfo(userInfo);return Ok(addUserInfo);}/// <summary>/// 事务添加用户信息/// </summary>/// <param name="userInfo">userInfo</param>/// <returns></returns>[HttpPost]public async Task<ActionResult<UserInfo>> AddUserInfoTransactions([FromBody] UserInfoReq userInfo){//TODO:单机服务器不支持事务使用【使用MongoDB事务会报错:Standalone servers do not support transactions】,只有在集群情况下才能用var addUserInfo = await _userOperationExampleServices.AddUserInfoTransactions(userInfo);return Ok(addUserInfo);}/// <summary>/// 用户信息修改/// </summary>/// <param name="id">id</param>/// <param name="userInfo">userInfo</param>/// <returns></returns>[HttpPut("{id}")]public async Task<ActionResult<UserInfo>> UpdateUserInfo(string id, [FromBody] UserInfoReq userInfo){var updateUserInfo = await _userOperationExampleServices.UpdateUserInfo(id, userInfo);return Ok(updateUserInfo);}/// <summary>/// 用户信息删除/// </summary>/// <param name="id">id</param>/// <returns></returns>[HttpDelete("{id}")]public async Task<ActionResult> Delete(string id){var deleteUser = await _userOperationExampleServices.Delete(id);return Ok(deleteUser);}}

注册数据库基础操作和工作单元

//注册数据库基础操作和工作单元
builder.Services.AddSingleton<IMongoConnection, MongoConnection>();
builder.Services.AddScoped<IMongoContext, MongoContext>();
builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();
builder.Services.AddScoped<IUserRepository, UserRepository>();

注册相关应用服务

builder.Services.AddScoped<IUserOperationExampleServices, UserOperationExampleServices>();

Swagger用户管理操作示例展示

添加用户信息

 添加成功,返回添加成功的用户信息:

通过用户ID获取对应用户信息

拿刚才添加成功的用户ID,查询用户信息:

获取所有用户信息

用户分页数据获取

查询第1页,显示10条数据:

查询第1页,显示2条数据:

 

 用户信息修改

指定要修改的字段内容,修改HeadPortrait、NickName、Status
参考文章:Update - MongoDB C# docs

 

 修改成功:

用户信息删除

输入需要删除的用户ID,点击Execute删除:

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

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

相关文章

Matplotlib plt.scatter:从入门到精通,只需一篇文章!

Matplotlib plt.scatter&#xff1a;从入门到精通&#xff0c;只需一篇文章&#xff01;&#x1f680; 利用Matplotlib进行数据可视化示例 &#x1f335;文章目录&#x1f335; 一、plt.scatter入门&#xff1a;轻松迈出第一步 &#x1f463;二、进阶探索&#xff1a;plt.scatt…

使用Docker Compose搭建Redis主从复制

在Docker中搭建Redis主从架构非常方便&#xff0c;下面是一个示例&#xff0c;演示一下如何使用Docker Compose搭建一个Redis主从复制环境。首先&#xff0c;确保我们本地环境已经安装了Docker和Docker Compose。 我这里使用OrbStack替代了Docker desktop。 1. 创建一个名为r…

Ansible file文件模块 设置文件的属性,比如创建文件、创建链接文件、删除文件

目录 语法创建目录创建链接文件删除文件 每个值的属性 语法 创建目录 ansible slave -m file -a path/data/app statedirectory path/data/app # 定义创建路径 statedirectory # 如果目录不存在就创建目录这就是创建目录成功之后的回显 可以看到&#xff0c;已经打印出目录a…

OLMo 以促进语言模型科学之名 —— OLMo Accelerating the Science of Language Models —— 全文翻译

OLMo: Accelerating the Science of Language Models OLMo 以促进语言模型科学之名 摘要 语言模型在自然语言处理的研究中和商业产品中已经变得无所不在。因为其商业上的重要性激增&#xff0c;所以&#xff0c;其中最强大的模型已经闭源&#xff0c;控制在专有接口之中&#…

stl~string

迭代器 typedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}iterator end(){return _str _size;}const_iterator begin() const//左值const{return _str;}const_iterator end() const{return _str _size;} for&#xff08;auto e : …

排序算法---计数排序

原创不易&#xff0c;转载请注明出处。欢迎点赞收藏~ 计数排序&#xff08;Counting Sort&#xff09;是一种线性时间复杂度的排序算法&#xff0c;其核心思想是通过统计待排序元素的个数来确定元素的相对位置&#xff0c;从而实现排序。 具体的计数排序算法步骤如下&#xff…

政安晨:【示例演绎】【Python】【Numpy数据处理】快速入门(一)

简介 NumPy是SciPy家族的成员之一。 SciPy家族是一个专门应用于数学、科学和工程领域的开源Python生态圈&#xff0c;或者说是一个由多个Python库组成的集合&#xff0c;用于解决科学计算中的各种问题。这些库构成了一个功能强大的科学计算工具箱&#xff0c;可以进行数值计算…

活用 Composition API 核心函数,打造卓越应用(上)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Vue2学习第三天

Vue2 学习第三天 1. 计算属性 computed 计算属性实现 定义&#xff1a;要用的属性不存在&#xff0c;要通过已有属性计算得来。 原理&#xff1a;底层借助了Objcet.defineproperty方法提供的getter和setter。 get函数什么时候执行&#xff1f; 初次读取时会执行一次。当依赖…

如何让Obsidian实现电脑端和安卓端同步

Obsidian是一款知名的笔记软件&#xff0c;支持Markdown语法&#xff0c;它允许用户在多个设备之间同步文件。要在安卓设备上实现同步&#xff0c;可以使用remote save插件&#xff0c;以下是具体操作步骤&#xff1a; 首先是安装电脑端的obsidian&#xff0c;然后依次下载obs…

Typora+PicGO+腾讯云COS做图床教程

文章目录 Typora&#xff0b;PicGO&#xff0b;腾讯云COS做图床教程一、为什么使用图床二、Typora、PicGO和腾讯云COS介绍三、下载Typora和PicGOTyporaPicGO 四、配置Typora、PicGO和腾讯云COS腾讯云COS配置PicGO配置Typora配置 Typora&#xff0b;PicGO&#xff0b;腾讯云COS做…

mysql 执行update操作 记录未修改

问题 mysql 执行update操作 记录未修改 详细问题 笔者进行SpringBootMybatis项目开发&#xff0c;确认执行update操作 控制台内容如下 Creating a new SqlSession SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession3cbe9459] was not registered for sync…

基于STM32的老人心率监测系统

1. 系统设计 本次课题为基于STM32的老人心率监测系统&#xff0c;在此设计了如图2.1所示的系统结构框图&#xff0c;整个系统包括了MAX30102心率血氧检测模块&#xff0c;SIM800短信模块&#xff0c;液晶显示模块&#xff0c;按键&#xff0c;ESP8266无线通信模块以及主控制器s…

【CV论文精读】【BEV感知】BEVFormer:通过时空Transformer学习多摄像机图像的鸟瞰图表示

【CV论文精读】BEVFormer Learning Bird’s-Eye-View Representation from Multi-Camera Images via Spatiotemporal Transformers BEVFormer&#xff1a;通过时空Transformer学习多摄像机图像的鸟瞰图表示 图1&#xff1a;我们提出了BEVFormer&#xff0c;这是一种自动驾驶的…

js基础篇

javascript 1.1javascript是什么&#xff1f; 是运行在浏览器【客户端】的编程语言 1.2 js的组成 ECMAScript (基础语法) Web APIs (DOM BOM) 1.3 js的书写位置 内部&#xff0c;外部&#xff0c;行内 【代码写在标签内部】 // 内部 <script>alter("你好&…

软件实例分享,药店进销存软件医药系统进销存教程

软件实例分享&#xff0c;药店进销存软件医药系统进销存教程 一、前言 以下软件程序教程以 佳易王药店进销存管理系统V16.0为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 软件可以对药品的有效期进行管理&#xff0c;可以查询还有多少天到期的…

云计算基础-网络虚拟化

虚拟交换机 什么是虚拟交换机 虚拟交换机是一种运行在虚拟化环境中的网络设备&#xff0c;其运行在宿主机的内存中&#xff0c;通过软件方式在宿主机内部实现了部分物理交换机的功能&#xff0c;如 VLAN 划分、流量控制、QoS 支持和安全功能等网络管理特性 虚拟交换机在云平…

编程语言的实际应用场景(C语言场景)

从应用范围上来说&#xff0c;这些编程语言大致可以分为两种&#xff1a; 一种是专用型语言&#xff0c;也就是针对某个特定领域而设计出来的语言&#xff1b;另一种是通用型语言&#xff0c;它们可以开发多种类型的应用程序&#xff0c;而不是局限在某个特定的领域。 专用型…

中科星图——LANDSAT_8/02/T1/TOA的Landsat8_C2_TOA类数据集

简介 数据名称&#xff1a; Landsat8_C2_TOA 数据来源&#xff1a; USGS 时空范围&#xff1a; 2020年1月-2023年3月 空间范围&#xff1a; 全国 数据简介&#xff1a; Landsat8_C2_TOA数据集是将数据每个波段的辐射亮度值转换为大气层顶表观反射率TOA&#xff0c;是…

如何解决缓存和数据库的数据不一致问题

数据不一致问题是操作数据库和操作缓存值的过程中&#xff0c;其中一个操作失败的情况。实际上&#xff0c;即使这两个操作第一次执行时都没有失败&#xff0c;当有大量并发请求时&#xff0c;应用还是有可能读到不一致的数据。 如何更新缓存 更新缓存的步骤就两步&#xff0…