当前位置: 首页 > news >正文

探索 .NET 9 控制台应用中的 LiteDB 异步 CRUD 操作

本文主要是使用异步方式,体验 litedb 基本的 crud 操作。

LiteDB 是一款轻量级、快速且免费的 .NET NoSQL 嵌入式数据库,专为小型本地应用程序设计。它以单一数据文件的形式提供服务,支持文档存储和查询功能,适用于桌面应用、移动应用和小型 Web 应用等场景。

LiteDB 的主要特点包括:

  • 无服务器的 NoSQL 文档存储LiteDB 是一个嵌入式数据库,无需独立服务器,数据存储在一个单一文件中,类似于 SQLite
  • 简单易用的 APILiteDB 提供类似 MongoDB 的简单 API,支持 LINQ 查询和 SQL-like 命令,使得开发者可以轻松上手。
  • 线程安全和 ACID 事务支持:LiteDB 支持线程安全操作和完整的 ACID 事务处理,确保数据的一致性和完整性。
  • 数据恢复功能LiteDB 使用写前日志(WAL)机制来保证数据恢复能力,即使在写入失败的情况下也能恢复数据。
  • 跨平台支持LiteDB 可以在 Windows、Linux 和 macOS 等多个平台上运行,具有良好的跨平台兼容性。
  • 加密存储LiteDB 支持使用 DESAES 加密算法对数据文件进行加密,保障数据的安全性。
  • 文件和流数据存储LiteDB 支持存储文件和流数据,类似于 MongoDBGridFS 功能。
  • 开源免费LiteDB 是一个开源(MIT)项目,任何人都可以使用和修改其代码,并且完全免费,包括商业用途。

LiteDB 的使用非常简单,可以通过 NuGet 包管理器轻松安装,并且提供了丰富的文档和示例代码帮助开发者快速上手。此外,LiteDB 还提供了一个名为 LiteDB Studio 的图形用户界面工具,方便用户管理和可视化数据库内容。

总之,LiteDB 是一款功能强大、易于使用的 NoSQL 数据库解决方案,适用于多种场景,值得开发者关注和尝试。

使用 .NET CLI 创建一个控制台应用程序,可以按照以下步骤进行:

  1. 安装 .NET 9 SDK:首先,确保你已经安装了 .NET 9 SDK。你可以从官方网站下载并安装最新版本的 .NET SDK

  2. 创建新的控制台应用程序:使用 dotnet new console 命令创建一个新的控制台应用程序。这个命令会生成一个包含基本结构的项目文件夹。

dotnet new console -n LiteDBExample
  1. 导航到项目目录:进入刚刚创建的项目目录。
 cd LiteDBExample
  1. 运行应用程序:使用 dotnet run 命令运行应用程序。
dotnet run

基础控制台项目就创建好了,丝滑般体验;

接下来我们使用 litedb 提供的 nuget 包,进行简单的封装,构建出异步操作的 crud 方法 。

  • 安装相关 nuget 包:
<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net9.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable></PropertyGroup><ItemGroup><PackageReference Include="LiteDB" Version="5.0.21" /><PackageReference Include="LiteDB.Async" Version="0.1.8" /><PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" /></ItemGroup></Project>
  • 创建实体类型 :Person
public class Person
{public Guid Id { get; set; } = Guid.NewGuid();public string Name { get; set; } = default!;public uint Age { get; set; }
}
  • 定义仓储类规范:IRepository
using LiteDB;namespace LiteDBExample.Core.Interfaces;public interface IRepository<TEntity> where TEntity : class
{Task<BsonValue> AddAsync(TEntity entity);Task<int> AddRangeAsync(IEnumerable<TEntity> entities);Task<IEnumerable<TEntity>> GetAllAsync();Task<TEntity?> GetByIdAsync(object id);Task<bool> UpdateAsync(TEntity entity);Task<int> UpdateRangeAsync(IEnumerable<TEntity> entities);Task<bool> DeleteAsync(object id);Task<int> DeleteRangeAsync(IEnumerable<object> ids);
}
  • 实现 PersonDbContext
using LiteDB;
using LiteDB.Async;
using LiteDBExample.Core.Entities;namespace LiteDBExample.Data;public class PersonDbContext(string connectionString) : IDisposable
{private readonly LiteDatabaseAsync _database = new(connectionString);public Task<BsonValue> AddAsync(Person person){var collection = _database.GetCollection<Person>("people");return collection.InsertAsync(person);}public Task<int> AddRangeAsync(IEnumerable<Person> persons){var collection = _database.GetCollection<Person>("people");return collection.InsertAsync(persons);}public Task<IEnumerable<Person>> GetAllAsync(){var collection = _database.GetCollection<Person>("people");return collection.FindAllAsync();}public Task<Person?> GetByIdAsync(object id){BsonValue bsonId = new(id);var collection = _database.GetCollection<Person>("people");return collection.FindByIdAsync(bsonId);}public Task<bool> UpdateAsync(Person person){var collection = _database.GetCollection<Person>("people");return collection.UpdateAsync(person);}public Task<int> UpdateRangeAsync(IEnumerable<Person> persons){var collection = _database.GetCollection<Person>("people");return collection.UpdateAsync(persons);}public Task<bool> DeleteAsync(object id){BsonValue bsonId = new(id);var collection = _database.GetCollection<Person>("people");return collection.DeleteAsync(bsonId);}public Task<int> DeleteRangeAsync(IEnumerable<object> ids){var collection = _database.GetCollection<Person>("people");return collection.DeleteManyAsync(a => ids.Contains(a.Id));}public void Dispose(){_database.Dispose();}
}
  • 定义 Person 类仓储:IPersonRepository
using LiteDBExample.Core.Entities;
using LiteDBExample.Core.Interfaces;namespace LiteDBExample.Repositories;public interface IPersonRepository : IRepository<Person>
{
}
  • 实现 Person 类仓储:PersonRepository
using LiteDB;
using LiteDBExample.Core.Entities;
using LiteDBExample.Data;namespace LiteDBExample.Repositories;public class PersonRepository(PersonDbContext context) : IPersonRepository
{private readonly PersonDbContext _context = context ?? throw new ArgumentNullException(nameof(context));public Task<BsonValue> AddAsync(Person entity){return _context.AddAsync(entity);}public Task<int> AddRangeAsync(IEnumerable<Person> entities){return _context.AddRangeAsync(entities);}public Task<IEnumerable<Person>> GetAllAsync(){return _context.GetAllAsync();}public Task<Person?> GetByIdAsync(object id){return _context.GetByIdAsync(id);}public Task<bool> UpdateAsync(Person entity){return _context.UpdateAsync(entity);}public Task<int> UpdateRangeAsync(IEnumerable<Person> entities){return _context.UpdateRangeAsync(entities);}public Task<bool> DeleteAsync(object id){return _context.DeleteAsync(id);}public Task<int> DeleteRangeAsync(IEnumerable<object> ids){return _context.DeleteRangeAsync(ids);}
}
  • Program.cs 中应用 IPersonRepository
using LiteDBExample.Core.Entities;
using LiteDBExample.Repositories;
using Microsoft.Extensions.DependencyInjection;
using LiteDBExample.Data;namespace LiteDBExample;internal class Program
{static async Task Main(string[] args){Console.WriteLine("Hello, LiteDB!");var services = new ServiceCollection();ConfigureServices(services);using var serviceProvider = services.BuildServiceProvider();var personRepository = serviceProvider.GetRequiredService<IPersonRepository>();// 多个 Personvar newPeople = new List<Person>{new Person { Name = "John Kiny", Age = 16 },new Person { Name = "John Doe", Age = 30 },new Person { Name = "Jane Smith", Age = 28 },new Person { Name = "Alice Johnson", Age = 35 }};try{Console.WriteLine("===> litedb Async Method Test");{// 添加单个 Personvar person = new Person { Name = "Alice Array", Age = 32 };var bsonId = await personRepository.AddAsync(person);Console.WriteLine($"bsonId={bsonId}");// 查询单个 Personvar queryPerson = await personRepository.GetByIdAsync(bsonId);Console.WriteLine($"guid={queryPerson.Id}, {queryPerson.Name} is {queryPerson.Age} years old.");// 更新单个 Personperson.Age += 1;person.Name = "Array";var updateCount = await personRepository.UpdateAsync(person);Console.WriteLine($"updateCount={updateCount}");// 删除单个 Personvar deleteCount = await personRepository.DeleteAsync(bsonId);Console.WriteLine($"deleteCount={deleteCount}");// 批量添加多个 Personint addRange = await personRepository.AddRangeAsync(newPeople);Console.WriteLine($"addRange={addRange}");// 查询所有 Personvar people = await personRepository.GetAllAsync();foreach (var p in people){Console.WriteLine($"guid={p.Id}, {p.Name} is {p.Age} years old.");}// 批量更新多个 Personvar updatedPeople = people.Select(p => new Person { Id = p.Id, Name = p.Name, Age = p.Age + 1 });int updateRows = await personRepository.UpdateRangeAsync(updatedPeople);Console.WriteLine($"updateRows={updateRows}");// 批量删除多个 Personvar idsToDelete = new List<object>();foreach (var item in people.Select(p => p.Id)){idsToDelete.Add(item);};var ids = idsToDelete.AsEnumerable();int deleteRows = await personRepository.DeleteRangeAsync(ids);Console.WriteLine($"deleteRows={deleteRows}");}Console.ReadLine();}catch (Exception ex){Console.WriteLine($"An error occurred: {ex.Message}");}}private static void ConfigureServices(IServiceCollection services){services.AddScoped<IPersonRepository, PersonRepository>();services.AddScoped<PersonDbContext>(provider => new PersonDbContext("filename=litedb_example.db"));}
}
  • 运行应用:dotnet run

dotnet run

  • 使用 LiteDB.Studio 工具查看 litedb 数据;

当批量添加数据的时候,查看数据信息如下:

  • Grid 查看

litedb-select-grid

  • Text 查看

litedb-select-text

从上图中可以看到 litedb_example.db 文件非常轻量,大概 30kb 左右;

相关文章:

探索 .NET 9 控制台应用中的 LiteDB 异步 CRUD 操作

本文主要是使用异步方式&#xff0c;体验 litedb 基本的 crud 操作。 LiteDB 是一款轻量级、快速且免费的 .NET NoSQL 嵌入式数据库&#xff0c;专为小型本地应用程序设计。它以单一数据文件的形式提供服务&#xff0c;支持文档存储和查询功能&#xff0c;适用于桌面应用、移动…...

《进程隔离机制:C++多进程编程安全的坚固堡垒》

在当今数字化时代&#xff0c;软件系统的安全性愈发成为人们关注的焦点。尤其是在 C多进程编程领域&#xff0c;如何确保进程间的安全交互与数据保护&#xff0c;是每一位开发者都必须面对的重要课题。而进程隔离机制&#xff0c;犹如一座坚固的堡垒&#xff0c;为 C多进程编程…...

构建无障碍的数字世界:深入探讨Web可访问性指南

文章目录 前言一、什么是Web可访问性&#xff1f;二、Web内容无障碍指南&#xff08;WCAG&#xff09;三、ARIA属性的应用四、实践中的Web可访问性结语 前言 在当今高度互联的世界里&#xff0c;互联网已成为人们日常生活不可或缺的一部分。然而&#xff0c;对于数百万残障人士…...

跨境出海安全:如何防止PayPal账户被风控?

今天咱们聊聊那些让人头疼的事儿——PayPal账户被风控。不少跨境电商商家反馈&#xff0c;我们只是想要安安静静地在网上做个小生意&#xff0c;结果不知道为什么&#xff0c;莫名其妙账户就被冻结了。 但其实每个封禁都是有原因的&#xff0c;今天就来给大家分享分享可能的原…...

学习日记_20241123_聚类方法(MeanShift)

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…...

AI编程和AI绘画哪个更适合创业?

AI编程和AI绘画各有优势&#xff0c;适合创业的方向取决于你的资源、兴趣、市场需求和技术能力。以下是两者的对比分析&#xff0c;帮助你选择更适合的方向&#xff1a; AI编程 优势 1、广泛应用领域&#xff1a; 涉及自动化、数据分析、自然语言处理、计算机视觉等多个领域&a…...

macOS 无法安装第三方app,启用任何来源的方法

升级新版本 MacOS 后&#xff0c;安装下载的软件时&#xff0c;不能在 ”安全性与隐私” 中找不到 ”任何来源” 选项。 1. 允许展示任何来源 点击 启动器 (Launchpad) – 其他 (Other) – 终端 (Terminal)&#xff1a; 打开终端后&#xff0c;输入以下代码回车&#xff1a; …...

关于SpringBoot集成Kafka

关于Kafka Apache Kafka 是一个分布式流处理平台&#xff0c;广泛用于构建实时数据管道和流应用。它能够处理大量的数据流&#xff0c;具有高吞吐量、可持久化存储、容错性和扩展性等特性。 Kafka一般用作实时数据流处理、消息队列、事件架构驱动等 Kafka的整体架构 ZooKeeper:…...

4.STM32之通信接口《精讲》之IIC通信---软件实现IIC《深入浅出》面试必备!

接下正式&#xff0c;进入软件编写IIC时序了&#xff0c;并实现对MPU6050的控制&#xff0c;既然是软件实现&#xff0c;那么硬件方面&#xff0c;我仅需两根控制线即可&#xff0c;即&#xff1a;数据控制线SDA&#xff0c;时钟控制线SCL。&#xff08;人为软件层面定义的&…...

6G通信技术对比5G有哪些不同?

6G&#xff0c;即第六代移动通信技术&#xff0c;是5G之后的延伸&#xff0c;代表了一种全新的通信技术发展方向。与5G相比&#xff0c;6G在多个方面都有显著的不同和提升&#xff0c;以下是对6G通信技术及其与5G差异的详细分析&#xff1a; 一、6G的基本特点 更高的传输速率…...

「Mac玩转仓颉内测版28」基础篇8 - 元组类型详解

本篇将介绍 Cangjie 中的元组类型&#xff0c;包括元组的定义、创建、访问、数据解构以及应用场景&#xff0c;帮助开发者掌握元组类型的使用。 关键词 元组类型定义元组创建元组访问数据解构应用场景 一、元组类型概述 在 Cangjie 中&#xff0c;元组是一种用于存储多种数据…...

WebStorm 2024.3/IntelliJ IDEA 2024.3出现elementUI提示未知 HTML 标记、组件引用爆红等问题处理

WebStorm 2024.3/IntelliJ IDEA 2024.3出现elementUI提示未知 HTML 标记、组件引用爆红等问题处理 1. 标题识别elementUI组件爆红 这个原因是&#xff1a; 在官网说明里&#xff0c;才版本2024.1开始&#xff0c;默认启用的 Vue Language Server&#xff0c;但是在 Vue 2 项目…...

机械设计学习资料

免费送大家学习资源&#xff0c;已整理好&#xff0c;仅供学习 下载网址&#xff1a; https://www.zzhlszk.com/?qZ02-%E6%9C%BA%E6%A2%B0%E8%AE%BE%E8%AE%A1%E8%A7%84%E8%8C%83SOP.zip...

Python 快速入门(上篇)❖ Python 字符串

Python 字符串 字符串格式化输出字符串拼接获取字符串长度字符串切片字符串处理方法 字符串格式化输出 name “xhx” age 30 # 方法1 print("我的名字是%s,今年%s岁了。 " % (name, age)) # 方法2 print(f"我的名字是{name},今年{age}岁了。")字符串拼接…...

Ubuntu中使用多版本的GCC

我的系统中已经安装了GCC11.4&#xff0c;在安装cuda时出现以下错误提示&#xff1a; 意思是当前的GCC版本过高&#xff0c;要在保留GCC11.4的同时安装GCC9并可以切换&#xff0c;可以通过以下步骤实现&#xff1a; 步骤 1: 安装 GCC 9 sudo apt-get update sudo apt-get ins…...

1+X应急响应(网络)文件包含漏洞:

常见网络攻击-文件包含漏洞&命令执行漏洞&#xff1a; 文件包含漏洞简介&#xff1a; 分析漏洞产生的原因&#xff1a; 四个函数&#xff1a; 产生漏洞的原因&#xff1a; 漏洞利用条件&#xff1a; 文件包含&#xff1a; 漏洞分类&#xff1a; 本地文件包含&#xff1a; …...

机器学习实战记录(1)

决策树——划分数据集 def splitDataSet(dataSet, axis, value): retDataSet [] #创建返回的数据集列表for featVec in dataSet: #遍历数据集if featVec[axis] value:reducedFeatVec featVec[:axis] #去掉axis特征reducedFeatVec.extend(featVec[axis1…...

PHP8解析php技术10个新特性

PHP8系列是 PHP编程语言的最新主线版本&#xff0c;带来了许多激动人心的新特性和改进。作为一名PHP开发者&#xff0c;了解这些更新能够帮助你编写更高效、安全和现代的代码。 8的核心技术知识点&#xff0c;包括语言特性、性能优化、安全增强以及开发者工具的改进。 Just-In…...

C++模版特化和偏特化

什么是模版特化 特化的含义&#xff1a;所谓特化&#xff0c;就是将泛型搞得具体化一些&#xff0c;从字面上来解释&#xff0c;就是为已有的模板参数进行一些使其特殊化的指定&#xff0c;使得以前不受任何约束的模板参数&#xff0c;或受到特定的修饰&#xff08;例如const或…...

Simulink中Model模块的模型保护功能

在开发工作过程中&#xff0c;用户为想要知道供应商的开发能力&#xff0c;想要供应商的模型进行测试。面对如此要求&#xff0c;为了能够尽快拿到定点项目&#xff0c;供应商会选择一小块算法或是模型以黑盒的形式供客户测试。Simulink的Model模块除了具有模块引用的功能之外&…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...