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

解锁 C# 与 LiteDB 嵌入式 NoSQL 数据库

一、开篇:邂逅 C# 与 LiteDB 新世界

在当今的软件开发领域,数据管理如同建筑的基石,而选择一款合适的数据库则是项目成功与否的关键因素之一。对于 C# 开发者来说,面对琳琅满目的数据库选项,如何抉择常常令人头疼。今天,就为大家揭开一款轻量级嵌入式 NoSQL 数据库 ——LiteDB 的神秘面纱,看看它与 C# 碰撞能擦出怎样奇妙的火花。

当我们开启一个新的 C# 项目,无论是桌面应用、移动应用,还是小型的后端服务,数据存储与读取的高效性、便捷性都是必须考量的重点。传统的关系型数据库固然强大,在处理复杂关联数据和事务时游刃有余,但对于一些追求简洁、快速部署,以及数据结构相对灵活的场景,嵌入式 NoSQL 数据库展现出了独特的优势。LiteDB 应运而生,它完全由 C# 编写,仿佛是为 C# 生态量身定制,能够无缝嵌入到应用程序中,无需额外的服务器配置,就像给你的代码世界增添了一个隐秘而强大的 “数据百宝箱”,让数据管理变得轻松自如。接下来,就让我们一步步走进 C# 与 LiteDB 构建的精彩天地。

二、LiteDB 初印象:轻量级的魔法盒子

2.1 是什么让 LiteDB 脱颖而出

LiteDB 是一款开源的嵌入式 NoSQL 数据库引擎,它完全由 C# 编写,天生就与 C# 应用程序有着极高的亲和力。其最为显著的特性之一就是小巧玲珑,整个数据库核心库通常仅有几百 KB 大小,以一个简单的.db 文件形式存在,无需像传统数据库那样依赖独立的服务器进程,能够直接嵌入到你的 C# 应用中,无论是 Windows 桌面应用、.NET Core 跨平台应用,还是基于 Xamarin 开发的移动端应用,都可以轻松携带这个 “数据百宝箱”,随时随地管理数据,仿佛给应用赋予了一个专属的、隐形的数据管家。

在数据存储格式上,LiteDB 采用 BSON(Binary JSON),这种格式既保留了 JSON 的灵活性与可读性,又在存储和传输效率上进行了优化,让结构化数据的存储变得游刃有余。对于开发者而言,LiteDB 还支持 LINQ 查询,这无疑是一大福音。熟悉 C# 的开发者们可以直接使用 LINQ 语法来操作数据库,无缝对接已有的编程习惯,降低学习成本,快速实现复杂的数据筛选、排序与聚合等操作,极大提升开发效率。同时,LiteDB 还具备 ACID 事务特性,能够确保在多操作并发场景下数据的原子性、一致性、隔离性与持久性,为数据安全保驾护航,即便在一些对数据完整性要求苛刻的小型商业应用场景下,也能稳稳应对。

2.2 适用场景大揭秘

小型桌面应用是 LiteDB 的 “主战场” 之一。想象一下,你正在开发一款个人记账软件,只需要记录日常收支、分类统计等简单数据,使用 LiteDB 就无需搭建复杂的数据库服务器,数据直接存储在本地的.db 文件中,软件启动迅速,操作流畅,即开即用,而且备份数据也仅仅是复制一个文件的事儿,像 Windows 下的便捷记账工具、Mac 上的待办事项清单应用等,LiteDB 都能完美适配,为应用赋予简洁而强大的数据管理能力。

在移动应用开发领域,特别是对于那些有本地数据存储需求,但又受限于移动端设备存储资源与网络条件的应用,LiteDB 同样表现卓越。以一款离线阅读的 APP 为例,它需要缓存文章内容、用户阅读进度等信息,LiteDB 可以在用户离线时高效存储这些数据,待网络恢复后再进行同步更新,凭借其轻量级特性,不会占用过多手机存储空间与电量,让应用在资源有限的移动端环境下依然能够提供稳定、流畅的数据服务。

对于物联网(IoT)设备而言,LiteDB 更是开启了数据管理的新大门。这些设备往往内存有限、算力不高,且通常处于分布式、弱网络甚至离线的工作环境。比如一个智能农业监测系统中的众多传感器节点,需要记录温湿度、光照强度等环境数据,LiteDB 能够以极小的资源开销嵌入到设备固件中,实时存储采集到的数据,在需要时供上位机或云端读取分析,实现对设备运行状态与环境信息的精准掌控,助力 IoT 设备在复杂多变的现实场景中稳定运行,发挥最大效能。

三、准备启航:安装与初始化

3.1 借助 NuGet 引入 LiteDB

在开启 LiteDB 之旅的第一步,就是要将它引入到我们的 C# 项目中。幸运的是,这一过程非常便捷,借助 NuGet 包管理器就能轻松搞定。

如果你是 Visual Studio 的忠实用户,只需右键单击你的 C# 项目,在弹出的菜单中选择 “管理 NuGet 程序包”,随后在打开的 NuGet 窗口中,切换到 “浏览” 选项卡,在搜索框中输入 “LiteDB”,稍等片刻,就能找到对应的包。点击 “安装” 按钮,Visual Studio 就会自动下载并安装 LiteDB 及其相关依赖项,整个过程一气呵成,就像为你的项目找到了一把开启数据宝藏的神奇钥匙。

要是你更习惯使用命令行工具,也没问题。打开命令行窗口,切换到你的项目目录下,输入 “Install-Package LiteDB” 并回车,.NET CLI 就会迅速响应,从 NuGet 源拉取 LiteDB 并安装到你的项目中,如同施展了一场无声的魔法,让 LiteDB 悄然融入你的代码世界。

3.2 创建你的数据库 “日记本”

成功引入 LiteDB 后,接下来就要创建我们的数据库了。在 LiteDB 中,数据库以一个.db 文件的形式存在,就如同一个装满数据的魔法日记本。

使用 LiteDatabase 类就能轻松创建或打开数据库连接,示例代码如下:

using LiteDB;
// 这里的 'path/to/your/database.db' 需要替换为你实际想要存放数据库文件的路径
var db = new LiteDatabase("path/to/your/database.db");

需要注意的是,这个路径既可以是绝对路径,也可以是相对路径。若使用相对路径,它通常是相对于你的应用程序启动目录而言。例如,你想把数据库文件放在项目的 “Data” 文件夹下,就可以写成 “Data/mydb.db”。在创建数据库时,如果指定路径下的.db 文件不存在,LiteDB 会自动帮你创建一个全新的数据库文件;要是文件已存在,它则会智能地打开已有数据库,确保你的数据随时待命,等待你的操作指令。初始化数据库连接这一步,就像是开启了通往数据世界的大门,为后续的数据存储与读取铺就了道路,让我们离高效管理数据的目标又近了一步。

四、数据建模:定义你的专属 “魔法蓝图”

在 LiteDB 的世界里,数据建模就像是绘制一张精密的魔法蓝图,它决定了我们如何组织和存储数据,让数据的管理更加有序、高效。在 LiteDB 中,一切皆可文档,这意味着我们可以通过创建简单的 C# 类来定义数据模型,每个类的实例就如同一份份独特的文档,被存储到数据库中。

以一个奇幻风格的 “巫师” 模型为例,假设我们要创建一个数据库来记录魔法学院中巫师们的信息,代码如下:

public class Wizard
{[BsonId]public int Id { get; set; } // 每个巫师的唯一标识,使用 [BsonId] 标记为主键,方便数据的快速检索与关联public string Name { get; set; } // 巫师的名字,如“哈利·波特”public int HouseId { get; set; } // 所属学院 ID,关联到学院信息public List<string> SpellsKnown { get; set; } // 掌握的魔法列表,体现复杂数据结构,支持存储多个魔法技能
}

在这个模型中,Id 属性被标记为 [BsonId],这是 LiteDB 识别文档主键的重要标识。就像现实世界中每个人都有独一无二的身份证号一样,主键确保了每个巫师记录在数据库中的唯一性,方便后续的数据查询、更新与删除操作能够精准定位到目标数据。Name 字段用于存储巫师的姓名,它是一个简单的字符串类型,直观地展现巫师的身份标识。HouseId 作为整数类型,关联着学院的唯一标识符,通过这个字段,我们可以轻松地建立起巫师与所属魔法学院之间的联系,实现数据之间的关联查询,比如查询某个学院下所有巫师的信息。而 SpellsKnown 字段则是一个 List 类型,它巧妙地展示了 LiteDB 处理复杂数据结构的能力,能够存储巫师所掌握的多个魔法技能,无论是简单的照明咒 “Lumos”,还是强大的守护咒 “Expecto Patronum”,都可以被有序地记录下来,让数据模型更加贴近真实的业务场景需求,为后续丰富多样的数据操作奠定坚实基础。通过精心设计这样的数据模型,我们就如同为数据库赋予了智慧的大脑,让它能够精准、高效地存储与管理数据,满足各类奇幻冒险般的业务需求。

五、核心魔法:增删查改全攻略

5.1 录入数据:挥动插入咒语

有了精心设计的数据模型和初始化的数据库连接,接下来就是向数据库中录入数据了,这就好比将一本本魔法秘籍放入我们的魔法图书馆。

在 LiteDB 中,使用 Insert 方法就能轻松实现数据插入。假设我们已经创建了 Wizard 模型,并且获取到了对应的集合 wizardsCollection(通过 db.GetCollection(“wizards”)),现在要插入哈利・波特的信息:

var harry = new Wizard
{Name = "Harry Potter",HouseId = 1,SpellsKnown = new List<string> { "Lumos", "Expelliarmus" }
};
wizardsCollection.Insert(harry);

这里,Insert 方法会将 harry 这个 Wizard 实例作为一个文档插入到 wizards 集合中。如果集合中还不存在 Id 值相同的文档,它会自动为 harry 分配一个唯一的 Id(若 Wizard 模型中的 Id 为自增类型,如 int 且无特殊设置,LiteDB 会按顺序递增生成;若 Id 为 ObjectId 等其他类型,也会按相应规则生成唯一标识)。需要注意的是,插入操作是幂等的,多次插入相同的文档(即具有相同 Id),除非集合设置了特殊的唯一索引约束,否则不会报错,但也不会重复插入数据,只是默默地忽略重复插入请求,确保数据的一致性与简洁性。

5.2 精准查找:念动查询密语

数据录入后,如何从海量的信息中精准捞出我们想要的数据呢?LiteDB 提供了强大的查询功能,让你仿佛拥有了一双洞察数据的 “魔法之眼”。

使用 FindOne 方法可以根据特定条件查找单个文档。比如,我们想要查找名为 “哈利・波特” 的巫师信息:

var harryFound = wizardsCollection.FindOne(w => w.Name == "Harry Potter");
if (harryFound!= null)
{Console.WriteLine($"找到巫师: {harryFound.Name}");Console.WriteLine($"所属学院: #{harryFound.HouseId}");Console.WriteLine($"掌握的魔法: {string.Join(", ", harryFound.SpellsKnown)}");
}
else
{Console.WriteLine("该巫师尚未加入我们的收藏!");
}

这段代码通过一个 Lambda 表达式 w => w.Name == “Harry Potter” 作为查询条件,精准定位到符合条件的巫师记录。若找到,便能详细展示其姓名、所属学院和掌握的魔法技能;若未找到,则给出友好提示。

而 FindAll 方法则更为强大,它能返回满足特定条件的所有文档。假设我们要查找所有属于格兰芬多学院(假设学院 ID 为 1)的巫师:

var gryffindors = wizardsCollection.FindAll(w => w.HouseId == 1);
foreach (var wizard in gryffindors)
{Console.WriteLine($"巫师: {wizard.Name},掌握魔法: {string.Join(", ", wizard.SpellsKnown)}");
}

这里利用 FindAll 结合条件查询,一次性捞出所有目标巫师信息,遍历输出,让数据一目了然。无论是简单的等值查询,还是复杂的包含、范围查询(如查询掌握特定魔法或魔法数量在某个区间的巫师),都可以通过灵活运用 LINQ 表达式来实现,满足各种刁钻的数据检索需求。

5.3 修改更新:施展改写魔法

在魔法世界里,巫师的成长伴随着魔法技能的提升与信息的变更,同样,在 LiteDB 中,数据也需要与时俱进地更新。

Update 方法就是我们手中的 “魔法修改笔”。例如,哈利・波特在冒险过程中学会了新魔法 “Expecto Patronum”,我们需要更新他的信息:

var updateResult = wizardsCollection.Update(w => w.Name == "Harry Potter",w => new Wizard { SpellsKnown = new List<string> { "Lumos", "Expelliarmus", "Expecto Patronum" } });

第一个参数 w => w.Name == “Harry Potter” 用于定位到要更新的目标文档,第二个参数则是一个新的 Wizard 实例,包含了更新后的魔法技能列表。LiteDB 会智能地比对新旧数据,仅更新发生变化的字段,高效且精准。需要注意的是,如果更新条件匹配不到任何文档,Update 操作将悄无声息地结束,不会引发错误,所以在执行更新前,最好先确认目标文档是否存在,或者结合查询操作来验证更新的必要性与准确性,确保数据更新按预期进行。

5.4 数据移除:释放删除魔力

当某些数据不再需要时,为了保持数据库的 “整洁”,就需要施展删除魔法了。

Delete 方法可以帮我们轻松移除指定的数据。比如,在一场大战后,我们要删除伏地魔(假设其名字为 “Voldemort”)的记录:

var deleteResult = wizardsCollection.Delete(w => w.Name == "Voldemort");

通过简单的条件表达式,就能精准地将符合条件的文档从集合中删除。如果条件匹配到多个文档,LiteDB 会一并将它们移除,确保数据清理的彻底性。与更新操作类似,若删除条件未找到匹配文档,Delete 操作也会平静地结束,不会报错,开发者需要自行把控删除条件的准确性,避免误删重要数据,维护数据的安全性与完整性。

六、进阶魔法:索引、事务与加密

6.1 索引加持:加速查询之旅

在数据库的世界里,随着数据量的不断增长,查询效率逐渐成为开发者关注的焦点。LiteDB 为我们提供了强大的索引功能,就如同在一本厚重的魔法书中创建了详细的目录,能够让数据查询瞬间定位,大大提升检索速度。

索引的原理基于特定的数据结构,它对文档中的某个或某些字段进行排序与存储,使得查询时无需遍历整个数据集,就能快速逼近目标数据。例如,在我们之前的 “巫师” 数据库中,如果经常需要根据巫师的名字来查找记录,那么为 Name 字段创建索引将极大优化查询性能。

创建索引的代码非常简洁,在获取集合后,使用 EnsureIndex 方法即可:

var wizardsCollection = db.GetCollection<Wizard>("wizards");
wizardsCollection.EnsureIndex(x => x.Name);

这里,EnsureIndex 方法会为 Wizard 类中的 Name 字段创建一个索引。创建索引后,当执行类似 FindOne(w => w.Name == “Harry Potter”) 这样的查询时,LiteDB 不再需要逐一比对每个文档的 Name 字段,而是借助索引快速定位到符合条件的文档,查询速度得到质的飞跃。尤其是在数据量达到成千上万条时,有无索引的查询耗时差异会非常明显,原本可能需要数秒甚至更长时间的查询,在索引的助力下,可能瞬间就能得到结果,让应用的响应速度得到极大提升,为用户带来流畅的数据交互体验。

6.2 事务保障:守护数据安全

在涉及多个数据操作且这些操作需要作为一个整体要么全部成功、要么全部失败的场景下,事务就如同数据世界的 “守护天使”,确保数据的一致性与完整性。

以一个简单的转账场景为例,假设我们有一个记录用户账户信息的数据库,包含 UserId、Balance 等字段。当用户 A 向用户 B 转账 100 金币时,需要先从用户 A 的账户扣除 100 金币,再向用户 B 的账户增加 100 金币,这两个操作必须同时成功,否则就会出现数据不一致的问题,比如 A 的钱扣了但 B 没收到,或者 B 收到钱了但 A 没扣款。

在 LiteDB 中,使用事务来保障这一过程的正确性:

using (var trans = db.BeginTrans())
{var usersCollection = db.GetCollection<User>("users");var userA = usersCollection.FindOne(u => u.UserId == "A");userA.Balance -= 100;usersCollection.Update(userA);var userB = usersCollection.FindOne(u => u.UserId == "B");userB.Balance += 100;usersCollection.Update(userB);trans.Commit();
}

在这段代码中,首先通过 BeginTrans 开启一个事务,然后在事务内执行对用户 A 和用户 B 账户的更新操作,如果在执行过程中没有出现异常,最后调用 Commit 方法提交事务,此时两个更新操作才会真正持久化到数据库;若在事务执行期间发生任何错误,比如数据库连接突然中断、更新操作违反了数据约束等,事务会自动回滚,之前对用户 A 和用户 B 账户所做的修改都会被撤销,确保数据库状态回到事务开始前的模样,数据的一致性和完整性得以完美守护,让应用在复杂的数据操作场景下稳如泰山。

6.3 加密防护:筑牢数据堡垒

在当今数字化时代,数据隐私与安全至关重要,尤其是涉及用户敏感信息的数据库,一旦泄露,后果不堪设想。LiteDB 为我们提供了加密数据文件的能力,如同给数据库披上了一层隐形的铠甲,让数据在存储层面就得到严密保护。

要对数据库文件进行加密,在创建 LiteDatabase 实例时,只需指定加密密钥即可:

using var db = new LiteDatabase("path/to/your/database.db", new LiteDB.FileOptions { Password = "mySecretKey" });

这里,mySecretKey 就是我们设置的加密密钥,它必须是 8 字节长度的字符串。设置加密后,LiteDB 会使用指定密钥对数据库文件进行加密存储,当应用程序读取数据时,也需要提供相同的密钥才能解密并正常访问数据。在实际应用中,对于金融类应用存储用户账户余额、交易记录,医疗类应用保存患者病历信息等场景,加密功能能够有效防止数据在存储介质上被非法获取与解读,确保用户隐私不被侵犯,让数据在安全的轨道上稳健运行,为应用的可靠发展保驾护航。

七、实战演练:打造一个小型应用

纸上得来终觉浅,让我们通过一个完整的实战案例,深入体会 C# 与 LiteDB 的强大组合。假设我们要开发一个简单的图书管理桌面应用程序,它需要实现图书信息的录入、查询、借阅管理以及统计分析等功能。

需求分析阶段,我们明确了应用的核心功能。对于图书信息,需要记录书名、作者、出版社、出版年份、ISBN 号以及库存数量等字段;借阅管理则涉及借阅人姓名、借阅时间、预计归还时间等信息。考虑到应用面向小型图书馆或个人藏书管理场景,数据量不大,且对部署便捷性要求较高,LiteDB 无疑是数据库的绝佳选择。

技术选型上,基于 Windows 平台开发,选用 C# 的 Windows Forms 框架搭建界面,结合 LiteDB 进行数据存储。这样既能利用 C# 的强大功能快速构建界面交互,又能借助 LiteDB 轻松管理数据,两者相得益彰。

在功能模块设计方面,主要分为图书信息管理、借阅管理与统计分析三大模块。图书信息管理模块负责图书的添加、编辑、删除与查询操作;借阅管理模块实现借阅记录的录入、归还操作以及逾期未还图书的提醒;统计分析模块则能按作者、出版社等维度统计图书数量,为图书馆员或个人藏书者提供数据洞察。

编码实现时,首先创建对应的 C# 数据模型类,如 Book 类和 Loan 类:

public class Book
{[BsonId]public int Id { get; set; }public string Title { get; set; }public string Author { get; set; }public string Publisher { get; set; }public int PublicationYear { get; set; }public string ISBN { get; set; }public int StockQuantity { get; set; }
}public class Loan
{[BsonId]public int Id { get; set; }public int BookId { get; set; }public string BorrowerName { get; set; }public DateTime BorrowDate { get; set; }public DateTime DueDate { get; set; }
}

接着,在应用启动时初始化 LiteDB 数据库连接:

using LiteDB;
public partial class MainForm : Form
{private LiteDatabase _db;public MainForm(){InitializeComponent();_db = new LiteDatabase("books.db");}
}

在图书信息管理模块,添加图书的代码如下:

var booksCollection = _db.GetCollection<Book>("books");
var newBook = new Book
{Title = txtTitle.Text,Author = txtAuthor.Text,Publisher = txtPublisher.Text,PublicationYear = int.Parse(txtPublicationYear.Text),ISBN = txtISBN.Text,StockQuantity = int.Parse(txtStockQuantity.Text)
};
booksCollection.Insert(newBook);

查询图书可根据不同条件灵活运用 FindOne 和 FindAll 方法,例如按书名查询:

var result = booksCollection.FindOne(b => b.Title.Contains(txtSearchTitle.Text));
if (result!= null)
{// 展示图书详细信息
}
else
{MessageBox.Show("未找到匹配图书");
}

借阅管理模块中,记录借阅信息:

var loansCollection = _db.GetCollection<Loan>("loans");
var newLoan = new Loan
{BookId = selectedBook.Id,BorrowerName = txtBorrowerName.Text,BorrowDate = DateTime.Now,DueDate = DateTime.Now.AddDays(14)
};
loansCollection.Insert(newLoan);

归还图书时,更新借阅记录并调整图书库存:

var loanToUpdate = loansCollection.FindOne(l => l.Id == selectedLoan.Id);
loanToUpdate.BorrowerName = "";
loanToUpdate.BorrowDate = default;
loanToUpdate.DueDate = default;
loansCollection.Update(loanToUpdate);var bookToUpdate = booksCollection.FindOne(b => b.Id == loanToUpdate.BookId);
bookToUpdate.StockQuantity++;
booksCollection.Update(bookToUpdate);

统计分析模块,按作者统计图书数量:

var authorStats = booksCollection.FindAll().GroupBy(b => b.Author).Select(g => new { Author = g.Key, Count = g.Count() });
foreach (var stat in authorStats)
{// 将统计结果展示在界面上
}

通过这个实战案例,我们清晰地看到 C# 与 LiteDB 如何默契配合,快速构建出功能完备的小型应用,满足实际业务需求,无论是个人开发者还是小型团队,都能利用这对组合高效开启项目开发之旅,让创意迅速落地为实用的软件产品。

八、总结:C# 与 LiteDB 的未来征程

至此,我们一同领略了 C# 与 LiteDB 携手带来的强大数据管理魔力。从初次相识 LiteDB 的轻量级魅力,到熟练运用它进行数据的增删查改、索引构建、事务处理以及数据加密,再到实战打造小型应用,每一步都见证了这对组合的高效与便捷。

LiteDB 凭借其小巧玲珑、嵌入式无服务器、支持复杂数据结构与 LINQ 查询等诸多优势,为 C# 开发者在小型项目、桌面应用、移动端以及物联网设备等领域的数据存储需求提供了近乎完美的解决方案。它极大地降低了开发门槛,让开发者能够将更多精力聚焦于业务逻辑创新,快速实现应用从构思到落地。

展望未来,随着技术的不断迭代演进,C# 语言本身在性能优化、语法糖拓展等方面持续进步,LiteDB 也势必紧跟步伐,进一步优化存储效率、查询性能,强化分布式场景下的协同能力,解锁更多高级功能。两者的深度融合将为开发者打开一扇通往更广阔创意天地的大门,无论是新兴的智能穿戴设备数据管理、跨平台的小型云服务构建,还是传统行业数字化转型中的各类小型系统开发,C# 与 LiteDB 都有望成为开发者手中的神兵利器,助力大家在创新的道路上扬帆远航,创造更多精彩绝伦的软件佳作。愿大家怀揣探索之心,持续挖掘这对组合的无限潜力,让代码世界绽放更耀眼光芒。

相关文章:

解锁 C# 与 LiteDB 嵌入式 NoSQL 数据库

一、开篇&#xff1a;邂逅 C# 与 LiteDB 新世界 在当今的软件开发领域&#xff0c;数据管理如同建筑的基石&#xff0c;而选择一款合适的数据库则是项目成功与否的关键因素之一。对于 C# 开发者来说&#xff0c;面对琳琅满目的数据库选项&#xff0c;如何抉择常常令人头疼。今…...

iOS - 数组的真实类型

1. NSArray 类簇 // 1. __NSArray0 (空数组) NSArray *empty [];// 2. __NSArrayI (不可变数组) NSArray *immutable [1, 2, 3];// 3. __NSArrayM (可变数组) NSMutableArray *mutable [NSMutableArray array];// 4. __NSSingleObjectArrayI (单元素数组) NSArray *single …...

Unity热更新 之 Addressables(2) 本地/远端打包 流程测试

基础篇&#xff1a;Unity热更新 之 Addressables(1) 资源基础加载-CSDN博客 基础方法来源于唐老狮,我也是初学热更这一块&#xff0c;所有不保证步骤完全正确&#xff0c;如有不足还请斧正 目录 0.前提 1.本地打包 1.1.资源放入包 1.2.简化路径名称给出标签(如有需要的话) …...

Python标准库之SQLite3

包含了连接数据库、处理数据、控制数据、自定义输出格式及处理异常的各种方法。 官方文档&#xff1a;sqlite3 --- SQLite 数据库的 DB-API 2.0 接口 — Python 3.13.1 文档 官方文档SQLite对应版本&#xff1a;3.13.1 SQLite主页&#xff1a;SQLite Home Page SQL语法教程&a…...

php 使用simplexml_load_string转换xml数据格式失败

本文介绍如何使用php函数解析xml数据为数组。 <?php$a <xml><ToUserName><![CDATA[ww8b77afac71336111]]></ToUserName><FromUserName><![CDATA[sys]]></FromUserName><CreateTime>1736328669</CreateTime><Ms…...

Linux第二课:LinuxC高级 学习记录day01

0、大纲 0.1、Linux 软件安装&#xff0c;用户管理&#xff0c;进程管理&#xff0c;shell 命令&#xff0c;硬链接和软连接&#xff0c;解压和压缩&#xff0c;功能性语句&#xff0c;结构性语句&#xff0c;分文件&#xff0c;make工具&#xff0c;shell脚本 0.2、C高级 …...

Notepad++上NppFTP插件的安装和使用教程

一、NppFTP插件下载 图示是已经安装好了插件。 在搜索框里面搜NppFTP&#xff0c;一般情况下&#xff0c;自带的下载地址容易下载失败。这里准备了一个下载连接&#xff1a;Release v0.29.10 ashkulz/NppFTP GitHub 这里我下载的是x86版本 下载好后在nodepad的插件里面选择打…...

怎样提高服务器中的数据传输速度?

服务器中的数据传输速度会影响着用户的体验感&#xff0c;当企业中的数据传输速度出现卡顿或者是过慢时&#xff0c;用户不能及时浏览到所需的内容&#xff0c;给用户造成不好的体验感&#xff0c;那么企业该怎样才能提高服务器中的数据传输速度呢&#xff1f; 服务器之间如何传…...

Java聊天小程序

拟设计一个基于 Java 技术的局域网在线聊天系统,实现客户端与服务器之间的实时通信。系统分为客户端和服务器端两类,客户端用于发送和接收消息,服务器端负责接收客户端请求并处理消息。客户端通过图形界面提供用户友好的操作界面,服务器端监听多个客户端的连接并管理消息通…...

Spring事件发布与监听

Spring事件机制详解&#xff1a;事件发布与监听 在Spring框架中&#xff0c;事件机制基于发布-订阅模式&#xff0c;允许组件之间进行解耦。发布者发布事件&#xff0c;监听者订阅并响应这些事件。Spring事件机制的核心在于ApplicationEvent和ApplicationListener&#xff0c;…...

【PPTist】公式编辑、插入音视频、添加动画

一、插入公式 点击公式的时候 latexEditorVisible 会变成 true src/views/Editor/CanvasTool/index.vue <Modalv-model:visible"latexEditorVisible" :width"880" ><LaTeXEditor close"latexEditorVisible false"update"data &…...

Dart语言的面向对象编程

Dart语言的面向对象编程 Dart是一种由谷歌开发的编程语言&#xff0c;主要用于构建Web、移动应用及服务器端应用。作为一门现代编程语言&#xff0c;Dart自带丰富的特性&#xff0c;尤其是在面向对象编程&#xff08;Object-Oriented Programming, OOP&#xff09;方面&#x…...

selenium+pyqt5自动化工具总结

说明&#xff1a;本工具是&#xff0c;操作外部google浏览器、selenium是无法操作qt界面中嵌套的浏览器的&#xff0c; 工具在后面 1. 代码结构 pycharm打开的文件下&#xff0c;再写一个子文件&#xff0c;文件导入的时候把子文件名带上 这样就可以在 外层使用命令 pyinst…...

Java 基于微信小程序的高校科研团队管理系统设计与实现(附源码,部署,文档

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…...

如何规模化实现完全自动驾驶?Mobileye提出解题“新”思路

在CES 2025上&#xff0c;Mobileye展示了端到端自动驾驶系统Mobileye Drive™&#xff0c;通过高度集成的传感器、算法和计算平台&#xff0c;可以实现自动驾驶功能的全覆盖。 Mobileye创始人兼首席执行官Amnon Shashua教授 期间&#xff0c;Mobileye创始人兼首席执行官Amnon …...

Vue2与Vue3在项目开发中的选择:深入探讨

文章目录 前言一、Vue2的优势与挑战二、Vue3的进步与特性三、如何做出选择&#xff1f;结语 前言 Vue.js 是一个用于构建用户界面的渐进式JavaScript框架。Vue2和Vue3是其两个主要版本&#xff0c;它们各自拥有一系列特点和优势。随着Vue3的发布&#xff0c;开发者们面临着在新…...

Git 操作与技巧

一、开发日常常用 Git 操作与技巧 1.1 基础操作 1.1.1 查看 Git 状态 git status&#xff1a;查看当前工作区的状态&#xff0c;了解哪些文件已经修改、哪些文件已经暂存。git status这个命令是最常用的命令之一&#xff0c;可以帮助你理解当前的开发状态&#xff0c;哪些文…...

vs2022开发.net窗体应用开发环境安装配置以及程序发布详细教程

文章目录 一、安装visual studio1.1推荐win10操作系统1.2推荐vs20221.3选择工作负载 二、新建基于.net的winform应用程序2.1为什么要.net 2.2 新建.net窗体应用2.2.1 选择Window窗体应用2.2.2 .net窗体对比framework窗体 三、发布.net应用 一、安装visual studio 1.1推荐win10…...

Mysql--基础篇--视图,存储过程,触发器

1、视图 MySQL视图&#xff08;View&#xff09;是一个虚拟表&#xff0c;其内容由查询定义。同真实的表一样&#xff0c;视图包含一系列带有名称的列和行数据。但是&#xff0c;视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表&#…...

代码随想录 哈希 test 8

18. 四数之和 - 力扣&#xff08;LeetCode&#xff09; 与三数之和类似&#xff0c;重点在剪枝和去重的区别&#xff0c;由于target可正可负&#xff0c;因此需要分两种情况讨论&#xff0c;如果target为正&#xff0c;则若当前选择的元素之和大于target&#xff0c;需要跳出这…...

Postman接口测试基本操作

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 Postman-获取验证码 需求&#xff1a;使用Postman访问验证码接口&#xff0c;并查看响应结果。 地址&#xff1a;http://kdtx-test.itheima.net/api/captchaIm…...

Three.js 渲染技术:打造逼真3D体验的幕后功臣

文章目录 前言一、着色器&#xff08;Shaders&#xff09;二、后处理&#xff08;Post-processing&#xff09;三、抗锯齿&#xff08;Anti-aliasing&#xff09;四、实时渲染与离线渲染五、光照模型与材质优化六、环境映射&#xff08;Environment Mapping&#xff09;七、纹理…...

uml活动图和用例图之间有一致性要求吗

UML&#xff08;统一建模语言&#xff09;中的活动图和用例图是两种不同的图表&#xff0c;它们用于描述软件系统的不同方面。尽管它们有不同的用途&#xff0c;但它们之间存在一定的一致性要求&#xff0c;以保证模型的有效性和准确性。 以下是活动图和用例图之间一致性要求的…...

嵌入式入门Day38

C Day1 第一个C程序C中的输入输出输出操作coutcin练习 命名空间使用方法自定义命名空间冲突问题 C对字符串的扩充C风格字符串的使用定义以及初始化C风格字符串与C风格字符串的转换C风格的字符串的关系运算常用的成员变量输入方法 布尔类型C对堆区空间使用的扩充作业 第一个C程序…...

什么叫区块链?怎么保证区块链的安全性?

区块链&#xff08;Blockchain&#xff09;是一种分布式数据库或账本技术&#xff0c;它通过去中心化的方式记录交易或其他数据&#xff0c;并确保这些记录是安全、透明和不可篡改的。区块链最初是作为比特币&#xff08;Bitcoin&#xff09;加密货币的基础技术而被公众所知&am…...

探秘block原理

01 概述 在iOS开发中&#xff0c;block大家用的都很熟悉了&#xff0c;是iOS开发中闭包的一种实现方式&#xff0c;可以对一段代码逻辑进行封装&#xff0c;使其可以像数据一样被传递、存储、调用&#xff0c;并且可以保存相关的上下文状态。 很多block原理性的文章都比较老&am…...

Unity2D初级背包设计后篇 拓展举例与不足分析

Unity2D初级背包设计中篇 MVC分层撰写(万字详解)-CSDN博客、 如果你已经搞懂了中篇&#xff0c;那么对这个背包的拓展将极为简单&#xff0c;我就在这里举个例子吧 目录 1.添加物品描述信息 2.拓展思路与不足分析 1.没有删除只有丢弃功能&#xff0c;所以可以添加垃圾桶 2.格…...

云计算基础,虚拟化原理

文章目录 一、虚拟化1.1 什么是虚拟化1.2 虚拟化类型 二 、存储虚拟化2.1 存储指标2.2 存储类型2.3 存储协议2.4 RAID 三、内存 i/O虚拟化3.1 内存虚拟化基本概念地址空间转换原理内存共享与隔离原理 3.2 I/O 虚拟化基本概念模拟&#xff08;Emulation&#xff09;方式半虚拟化…...

Android13工具修改wifi mac地址以后没有更新的问题

Android13系统在通过烧写工具更新修改wifi mac地址以后&#xff0c;在系统设置里面查看wifi mac地址还是之前的&#xff0c;没有更新。 原因&#xff1a;android13 系统中packages\modules\Wifi\service\ServiceWifiResources\res\values\config.xml新增了"config_wifiSav…...

Jmeter_后置处理beanshell

背景&#xff1a;调用Eolinker接口&#xff0c;统计接口测试用例的完成情况&#xff0c;并写入excel文件&#xff1b; 1、调用登录接口&#xff0c;JSON提取器提取接口返回的accessToken&#xff0c;再封装到HTTP信息头管理器中&#xff1b; 2、请求工作空间列表接口&#xff0…...

熵与交叉熵:从不确定性角度理解 KL 散度

从不确定性减少视角理解KL散度 损失函数相关文章&#xff08;置顶&#xff09; 1. KL 散度&#xff1a;多维度解读概率分布间的隐秘 “距离” 2. 熵与交叉熵&#xff1a;从不确定性角度理解 KL 散度 3. 机器学习、深度学习关于熵你所需要知道的一切 本文核心 由于熵表征不确定…...

HarmonyOS鸿蒙开发 弹窗及加载中指示器HUD功能实现

HarmonyOS鸿蒙开发 弹窗及加载中指示器HUD功能实现 最近在学习鸿蒙开发过程中&#xff0c;阅读了官方文档&#xff0c;在之前做flutter时候&#xff0c;经常使用overlay&#xff0c;使用OverlayEntry加入到overlayState来做添加悬浮按钮、提示弹窗、加载中指示器、加载失败的t…...

KG-CoT:基于知识图谱的大语言模型问答的思维链提示

一些符号定义 知识图谱实体数量&#xff1a; n n n 知识图谱中关系类型数量&#xff1a; m m m 三元组矩阵&#xff1a; M ∈ { 0 , 1 } n n m \textbf{M} \in \{0, 1\}^{n \times n \times m} M∈{0,1}nnm&#xff0c; M i j k 1 M_{ij}^k 1 Mijk​1则说明实体 i i i和实…...

(2024,影响 LLaVA 性能的因素,LLM 模型规模,视觉输入配置(网格/token 数),AnyRes,数据量/质量)

LLaVA-NeXT: What Else Influences Visual Instruction Tuning Beyond Data? 目录 0. 简介 1. 架构 1.1 语言模型 1.2 视觉编码器 2. 视觉表示 2.1 训练时分辨率和 token 数量配置 2.2 LLM 扩展的有效性 2.3 放大原始图像 2.4 推理时分辨率和 token 数量配置 2.5 池…...

Vue3 网络请求

文章目录 Vue3 网络请求CORS问题ajaxfetchaxios Vue3 网络请求 CORS问题 同源&#xff1a;指的是当前用户所在的URL与被请求的URL的协议名、域名、端口必须完全相同。一旦有一个或多个不同&#xff0c;就是非同源请求&#xff0c;也就是我们经常说的跨域请求&#xff0c;简称…...

全方位解读消息队列:原理、优势、实例与实践要点

全方位解读消息队列&#xff1a;原理、优势、实例与实践要点 一、消息队列基础认知 在数字化转型浪潮下&#xff0c;分布式系统架构愈发复杂&#xff0c;消息队列成为其中关键一环。不妨把消息队列想象成一个超级“信息驿站”&#xff0c;在古代&#xff0c;各地的信件、物资运…...

Java-数据结构-栈与队列(StackQueue)

一、栈(Stack) ① 栈的概念 栈是一种特殊的线性表&#xff0c;它只允许固定一端进行"插入元素"和"删除元素"的操作&#xff0c;这固定的一端被称作"栈顶"&#xff0c;对应的另一端就被称做"栈底"。 &#x1f4da; 栈中的元素遵循后…...

Transformer入门教程全解析(一)

一、开篇&#xff1a;走进Transformer的奇妙世界 在当今深度学习领域&#xff0c;Transformer 无疑是一颗璀璨的明星&#xff0c;它如同一股强大的变革力量&#xff0c;席卷了自然语言处理&#xff08;NLP&#xff09;乃至更多领域。从机器翻译到文本生成&#xff0c;从问答系…...

拼音读音基础

文章目录 一、音节1、结构2、声母3、韵母 二、声调 拼音读音往往被认为跟应试考试相关&#xff0c;学会正常交流口语以后不再进行关注&#xff0c;其实还是有必要了解细节、查漏补缺。 一、音节 1、结构 音节 声母 韵母&#xff1b;一个音节基本等于一个汉字&#xff1b; 2、…...

Qt 坐标系统和坐标变换

一、概述:1、QPainter在QPaintDevice上绘图的默认坐标系统是&#xff0c;原点(0,0)在左上角&#xff0c;x轴正方向水平向右&#xff0c;y轴正方向竖直向下的坐标系。 2、为了绘图的方便&#xff0c;QPainter提供了一些坐标变换的功能&#xff0c;通过平移、旋转、缩放等坐标变…...

【redis】ubuntu18安装redis7

在Ubuntu 18下安装Redis7可以通过以下两种方法实现&#xff1a;手动编译安装和使用APT进行安装。 Ubuntu 18系统的环境和版本&#xff1a; $ cat /proc/version Linux version 4.15.0-213-generic (builddlcy02-amd64-079) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)…...

Outlook 网页版一直提示:检测到重复的重定向

Outlook 网页版提示“检测到重复的重定向”通常是由于浏览器缓存、Cookie问题或浏览器插件引发的。可以按照以下步骤进行排查和解决&#xff1a; 1. 清除浏览器缓存和 Cookie 在浏览器设置中找到清除浏览数据的选项。勾选“缓存文件”和“Cookies”相关选项&#xff0c;然后清…...

初级前端面试题 - js

前言&#xff1a;众所周知&#xff0c;HTML,CSS,JS是学习前端所必备的。js的基础学好了&#xff0c;框架类的vue,react等都会接受的很快&#xff0c;因此js是前端很总要的一个部分&#xff0c;这篇文章将会结合面试题&#xff0c;对js的知识点进行总结 号外号外&#xff0c;这是…...

matlab的绘图的标题中(title)添加标量以及格式化输出

有时候我们需要在matlab绘制的图像的标题中添加一些变量&#xff0c;这样在修改某些参数后&#xff0c;标题会跟着一块儿变。可以采用如下的方法&#xff1a; x -10:0.1:10; %x轴的范围 mu 0; %均值 sigma 1; %标准差 y normpdf(x,mu,sigma); %使用normpdf函数生成高斯函数…...

51单片机——串口通信(重点)

1、通信 通信的方式可以分为多种&#xff0c;按照数据传送方式可分为串行通信和并行通信&#xff1b; 按照通信的数据同步方式&#xff0c;可分为异步通信和同步通信&#xff1b; 按照数据的传输方向又可分为单工、半双工和全双工通信 1.1 通信速率 衡量通信性能的一个非常…...

mapbox基础,style样式汇总,持续更新

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;mapbox 从入门到精通 文章目录 一、&#x1f340;前言二、&#x1f340;根属性2.1 so…...

用AI技术提升Flutter开发效率:ScriptEcho的力量

引言 在当今快速发展的技术时代&#xff0c;Flutter作为一种跨平台开发框架&#xff0c;正在越来越多的开发者中崭露头角。它不仅能够为开发者提供一套代码同时部署到iOS和Android平台的解决方案&#xff0c;还能帮助企业节省人力成本和开发时间。然而&#xff0c;对于新手开发…...

Java阶段四04

第4章-第4节 一、知识点 CSRF、token、JWT 二、目标 理解什么是CSRF攻击以及如何防范 理解什么是token 理解什么是JWT 理解session验证和JWT验证的区别 学会使用JWT 三、内容分析 重点 理解什么是CSRF攻击以及如何防范 理解什么是token 理解什么是JWT 理解session验…...

vivado 时钟指南

时钟指南 每个 FPGA 架构都为时钟提供有专用资源。掌握 FPGA 架构中的时钟资源&#xff0c;使您能够规划好自己的时钟&#xff0c;从而实现时钟 资源的最佳利用。大多数设计无需您了解这些细节。但如果您能够控制布局&#xff0c;同时对每个时钟域上的扇出有良好的思 路&a…...

git项目提交步骤(简洁版)

1.创建仓库 2.填写 信息 3.点击这个按钮 4.找到要上传的文件&#xff0c;在目录内右键点击 5.依次执行命令 在命令窗口中输入&#xff1a;git init 复制仓库地址&#xff1a; 在命令窗口中输入&#xff1a;git remote add origin 仓库地址 在命令窗口中输入&#xff1a;…...