2025-11-09
LiteDB
00

目录

事务的ACID特性
A - 原子性(Atomicity)
C - 一致性(Consistency)
I - 隔离性(Isolation)
D - 持久性(Durability)
LiteDB 显式事务管理
Nuget 安装LiteDB
基本显式事务示例
事务回滚场景
LiteDB 隐式事务应用
单一操作的隐式事务
批量操作的隐式事务
5. 注意事项
结论

在现代软件开发中,数据的可靠性和一致性至关重要。每一个数据库操作都潜藏着风险:一个意外的系统崩溃、一个未处理的异常,都可能导致数据的部分损坏或完全丢失。这就是为什么事务管理成为数据库设计中最关键的特性之一。

对于追求轻量级、高效率的开发者来说,LiteDB 是一个令人兴奋的选择。它不仅提供了简单直观的 API,还内置了强大的事务管理机制。本文将深入探索 LiteDB 的事务世界,揭示如何通过精妙的事务控制,为您的应用程序构建坚不可摧的数据保护屏障。

无论您是一名经验丰富的开发者,还是刚开始接触数据库编程的新手,这篇文章都将为您呈现 LiteDB 事务管理的方方面面:从基本的 ACID 特性,到复杂的事务处理模式,我们将带您穿越数据一致性的迷雾,直达技术的璀璨之巅。

事务的ACID特性

事务(Transaction)是数据库管理系统中确保数据一致性和完整性的关键机制。在 LiteDB 中,事务遵循经典的 ACID 特性:

A - 原子性(Atomicity)

  • 事务中的所有操作要么全部成功,要么全部回滚
  • 保证了数据操作的不可分割性

C - 一致性(Consistency)

  • 事务执行前后,数据库的状态必须保持一致
  • 防止事务导致数据库处于不合法的状态

I - 隔离性(Isolation)

  • 并发执行的事务相互隔离,互不影响
  • 防止多个事务同时操作同一数据时产生冲突

D - 持久性(Durability)

  • 事务一旦提交,其修改将永久保存
  • 即使系统发生故障,已提交的事务不会丢失

LiteDB 显式事务管理

Nuget 安装LiteDB

image.png

基本显式事务示例

C#
// 用户实体类 public class User { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } }
C#
using LiteDB; namespace App12 { internal class Program { static void Main(string[] args) { PerformExplicitTransaction(); } public static void PerformExplicitTransaction() { // 使用数据库连接字符串创建数据库实例 using (var db = new LiteDatabase(@"MyDatabase.db")) { try { // 开始显式事务 db.BeginTrans(); // 获取用户集合 var users = db.GetCollection<User>("users"); // 执行多个操作 var newUser = new User { Name = "张三", Age = 30 }; users.Insert(newUser); // 更新另一个用户 var existingUser = users.FindOne(u => u.Name == "李四"); if (existingUser != null) { existingUser.Age += 1; users.Update(existingUser); } // 提交事务 db.Commit(); Console.WriteLine("事务成功提交"); } catch (Exception ex) { // 发生异常时回滚事务 db.Rollback(); Console.WriteLine($"事务回滚:{ex.Message}"); } } } } }

image.png

image.png

事务回滚场景

C#
using LiteDB; namespace App12 { // 定义银行账户类 public class BankAccount { public ObjectId Id { get; set; } public string AccountNumber { get; set; } public decimal Balance { get; set; } } internal class Program { static void Main(string[] args) { // 先初始化数据 InitializeDatabase(); Console.WriteLine("转账演示开始..."); Console.WriteLine("-------------------"); // 显示初始余额 DisplayAllAccounts(); // 执行转账操作 TransactionRollbackDemo(); // 显示转账后的余额 Console.WriteLine("\n转账后的账户余额:"); DisplayAllAccounts(); } // 初始化数据库 public static void InitializeDatabase() { using (var db = new LiteDatabase(@"MyDatabase.db")) { var accounts = db.GetCollection<BankAccount>("accounts"); // 清空已有数据 accounts.DeleteAll(); // 插入初始账户 accounts.Insert(new BankAccount { AccountNumber = "1001", Balance = 1000 }); accounts.Insert(new BankAccount { AccountNumber = "1002", Balance = 1000 }); Console.WriteLine("数据库初始化完成"); } } // 显示所有账户余额 public static void DisplayAllAccounts() { using (var db = new LiteDatabase(@"MyDatabase.db")) { var accounts = db.GetCollection<BankAccount>("accounts"); var allAccounts = accounts.FindAll(); Console.WriteLine("\n当前所有账户余额:"); foreach (var account in allAccounts) { Console.WriteLine($"账户 {account.AccountNumber}: {account.Balance:C}"); } } } public static void TransactionRollbackDemo() { using (var db = new LiteDatabase(@"MyDatabase.db")) { db.BeginTrans(); try { var accounts = db.GetCollection<BankAccount>("accounts"); // 模拟银行转账 var fromAccount = accounts.FindOne(a => a.AccountNumber == "1001"); var toAccount = accounts.FindOne(a => a.AccountNumber == "1002"); decimal transferAmount = 1500; // 转账金额大于余额,将触发异常 Console.WriteLine($"\n尝试从账户 {fromAccount.AccountNumber} 转账 {transferAmount:C} 到账户 {toAccount.AccountNumber}"); // 检查余额是否充足 if (fromAccount.Balance < transferAmount) { // 余额不足,抛出异常触发回滚 throw new InvalidOperationException("余额不足,无法转账"); } // 扣除转出账户余额 fromAccount.Balance -= transferAmount; accounts.Update(fromAccount); // 增加转入账户余额 toAccount.Balance += transferAmount; accounts.Update(toAccount); // 提交事务 db.Commit(); Console.WriteLine("转账成功"); } catch (Exception ex) { // 发生异常,回滚所有操作 db.Rollback(); Console.WriteLine($"转账失败:{ex.Message}"); } } } } }

image.png

LiteDB 隐式事务应用

单一操作的隐式事务

LiteDB 对于单个操作(如插入、更新、删除)会自动管理事务:

C#
using LiteDB; namespace App12 { public class Product { public ObjectId Id { get; set; } // 使用 LiteDB 的 ObjectId 作为主键 public string Name { get; set; } public decimal Price { get; set; } public int Stock { get; set; } // 添加库存字段 public DateTime CreatedDate { get; set; } } internal class Program { static void Main(string[] args) { // 初始化产品数据 InitializeProducts(); Console.WriteLine("初始产品列表:"); DisplayAllProducts(); // 测试隐式事务 ImplicitTransactionDemo(); Console.WriteLine("\n操作后的产品列表:"); DisplayAllProducts(); } public static void InitializeProducts() { using (var db = new LiteDatabase(@"MyDatabase.db")) { var products = db.GetCollection<Product>("products"); // 清空现有数据 products.DeleteAll(); // 插入初始产品数据 products.Insert(new Product { Name = "智能手机", Price = 3999.99m, Stock = 50, CreatedDate = DateTime.Now }); products.Insert(new Product { Name = "平板电脑", Price = 4599.99m, Stock = 30, CreatedDate = DateTime.Now }); // 创建索引 products.EnsureIndex(x => x.Name); Console.WriteLine("产品数据初始化完成"); } } public static void DisplayAllProducts() { using (var db = new LiteDatabase(@"MyDatabase.db")) { var products = db.GetCollection<Product>("products"); var allProducts = products.FindAll(); Console.WriteLine("\n产品列表:"); Console.WriteLine("----------------------------------------"); Console.WriteLine("名称\t\t价格\t\t库存\t创建时间"); Console.WriteLine("----------------------------------------"); foreach (var product in allProducts) { Console.WriteLine($"{product.Name,-16}{product.Price,10:C}{product.Stock,8}\t{product.CreatedDate:yyyy-MM-dd}"); } Console.WriteLine("----------------------------------------"); } } public static void ImplicitTransactionDemo() { using (var db = new LiteDatabase(@"MyDatabase.db")) { var products = db.GetCollection<Product>("products"); try { // 1. 插入新产品(单一操作,LiteDB 自动管理事务) var newProduct = new Product { Name = "笔记本电脑", Price = 5999.99m, Stock = 20, CreatedDate = DateTime.Now }; products.Insert(newProduct); Console.WriteLine("\n新产品添加成功:" + newProduct.Name); // 2. 更新现有产品价格(原子操作) var existingProduct = products.FindOne(p => p.Name == "智能手机"); if (existingProduct != null) { decimal oldPrice = existingProduct.Price; existingProduct.Price -= 500; products.Update(existingProduct); Console.WriteLine($"\n产品'{existingProduct.Name}'价格更新成功:"); Console.WriteLine($"原价:{oldPrice:C} -> 新价:{existingProduct.Price:C}"); } // 3. 补充库存(原子操作) var tabletProduct = products.FindOne(p => p.Name == "平板电脑"); if (tabletProduct != null) { int oldStock = tabletProduct.Stock; tabletProduct.Stock += 10; products.Update(tabletProduct); Console.WriteLine($"\n产品'{tabletProduct.Name}'库存更新成功:"); Console.WriteLine($"原库存:{oldStock} -> 新库存:{tabletProduct.Stock}"); } // 4. 删除过期产品(如果存在) var result = products.DeleteMany(p => p.CreatedDate < DateTime.Now.AddYears(-1)); if (result > 0) { Console.WriteLine($"\n删除了 {result} 个过期产品"); } } catch (Exception ex) { Console.WriteLine($"\n操作出错:{ex.Message}"); } } } // 添加一个辅助方法来搜索产品 public static void SearchProducts(string keyword) { using (var db = new LiteDatabase(@"MyDatabase.db")) { var products = db.GetCollection<Product>("products"); var searchResults = products.Find(p => p.Name.Contains(keyword)); Console.WriteLine($"\n搜索结果 (关键词: {keyword}):"); Console.WriteLine("----------------------------------------"); foreach (var product in searchResults) { Console.WriteLine($"{product.Name} - {product.Price:C} - 库存:{product.Stock}"); } Console.WriteLine("----------------------------------------"); } } } }

image.png

批量操作的隐式事务

对于批量操作,建议使用显式事务以获得更好的性能和控制:

C#
using LiteDB; using System; using System.Collections.Generic; using System.Linq; namespace App12 { public class Order { public ObjectId Id { get; set; } public string OrderNumber { get; set; } public DateTime OrderDate { get; set; } public decimal TotalAmount { get; set; } public string CustomerName { get; set; } public string Status { get; set; } // 订单状态:Pending, Completed, Cancelled public List<OrderItem> Items { get; set; } } public class OrderItem { public string ProductName { get; set; } public int Quantity { get; set; } public decimal UnitPrice { get; set; } public decimal Subtotal => Quantity * UnitPrice; } internal class Program { static void Main(string[] args) { var program = new Program(); Console.WriteLine("开始批量订单操作演示..."); program.BatchOperationDemo(); Console.WriteLine("\n订单统计信息:"); program.DisplayOrderStatistics(); } public void BatchOperationDemo() { using (var db = new LiteDatabase(@"MyDatabase.db")) { var orders = db.GetCollection<Order>("orders"); // 清空现有订单 orders.DeleteAll(); // 创建索引 orders.EnsureIndex(x => x.OrderNumber, unique: true); orders.EnsureIndex(x => x.OrderDate); orders.EnsureIndex(x => x.CustomerName); // 使用显式事务处理批量操作 try { db.BeginTrans(); Console.WriteLine("开始生成订单..."); // 批量插入订单 var newOrders = GenerateOrders(100); orders.InsertBulk(newOrders); // 模拟一些额外的操作 UpdateRandomOrderStatus(orders); db.Commit(); Console.WriteLine($"成功插入 {newOrders.Count()} 个订单"); // 显示一些示例订单 DisplaySampleOrders(orders); } catch (Exception ex) { db.Rollback(); Console.WriteLine($"批量操作失败:{ex.Message}"); } } } private IEnumerable<Order> GenerateOrders(int count) { var random = new Random(); var customers = new[] { "张三", "李四", "王五", "赵六", "钱七" }; var products = new[] { ("笔记本电脑", 5999m), ("智能手机", 3999m), ("平板电脑", 2999m), ("智能手表", 1999m), ("蓝牙耳机", 999m) }; for (int i = 0; i < count; i++) { var orderItems = new List<OrderItem>(); var itemCount = random.Next(1, 4); // 每个订单1-3个商品 for (int j = 0; j < itemCount; j++) { var product = products[random.Next(products.Length)]; orderItems.Add(new OrderItem { ProductName = product.Item1, Quantity = random.Next(1, 4), UnitPrice = product.Item2 }); } var order = new Order { OrderNumber = $"ORD{DateTime.Now:yyyyMMdd}{i + 1:D4}", OrderDate = DateTime.Now.AddDays(-random.Next(0, 30)), CustomerName = customers[random.Next(customers.Length)], Status = "Pending", Items = orderItems, TotalAmount = orderItems.Sum(item => item.Subtotal) }; yield return order; } } private void UpdateRandomOrderStatus(ILiteCollection<Order> orders) { var random = new Random(); var statuses = new[] { "Completed", "Cancelled" }; // 随机更新一些订单状态 var someOrders = orders.Find(Query.All(), limit: 20); foreach (var order in someOrders) { if (random.Next(2) == 0) // 50% 的概率更新状态 { order.Status = statuses[random.Next(statuses.Length)]; orders.Update(order); } } } private void DisplaySampleOrders(ILiteCollection<Order> orders) { Console.WriteLine("\n示例订单信息:"); Console.WriteLine("----------------------------------------"); var sampleOrders = orders.Find(Query.All(), limit: 5); foreach (var order in sampleOrders) { Console.WriteLine($"订单号: {order.OrderNumber}"); Console.WriteLine($"客户: {order.CustomerName}"); Console.WriteLine($"日期: {order.OrderDate:yyyy-MM-dd}"); Console.WriteLine($"状态: {order.Status}"); Console.WriteLine("商品列表:"); foreach (var item in order.Items) { Console.WriteLine($" - {item.ProductName} x {item.Quantity} @ {item.UnitPrice:C} = {item.Subtotal:C}"); } Console.WriteLine($"总金额: {order.TotalAmount:C}"); Console.WriteLine("----------------------------------------"); } } public void DisplayOrderStatistics() { using (var db = new LiteDatabase(@"MyDatabase.db")) { var orders = db.GetCollection<Order>("orders"); var totalOrders = orders.Count(); var totalAmount = orders.FindAll().Sum(o => o.TotalAmount); var pendingOrders = orders.Count(Query.EQ("Status", "Pending")); var completedOrders = orders.Count(Query.EQ("Status", "Completed")); var cancelledOrders = orders.Count(Query.EQ("Status", "Cancelled")); Console.WriteLine($"订单总数: {totalOrders}"); Console.WriteLine($"订单总金额: {totalAmount:C}"); Console.WriteLine($"待处理订单: {pendingOrders}"); Console.WriteLine($"已完成订单: {completedOrders}"); Console.WriteLine($"已取消订单: {cancelledOrders}"); // 按客户统计 var customerOrders = orders.FindAll() .GroupBy(o => o.CustomerName) .Select(g => new { Customer = g.Key, OrderCount = g.Count(), TotalAmount = g.Sum(o => o.TotalAmount) }) .OrderByDescending(x => x.TotalAmount); Console.WriteLine("\n客户订单统计:"); Console.WriteLine("----------------------------------------"); foreach (var stat in customerOrders) { Console.WriteLine($"客户: {stat.Customer}"); Console.WriteLine($"订单数: {stat.OrderCount}"); Console.WriteLine($"总金额: {stat.TotalAmount:C}"); Console.WriteLine("----------------------------------------"); } } } } }

image.png

5. 注意事项

  • LiteDB 是一个轻量级的嵌入式数据库,事务管理相对简单
  • 对于高并发场景,可能需要考虑更复杂的并发控制机制
  • 始终关注异常处理和事务回滚逻辑
  • 对于复杂的、多步骤的数据库操作,始终使用显式事务
  • 尽可能缩小事务的作用范围,提高并发性能
  • 捕获并处理可能的异常,确保事务能正确回滚
  • 对于大批量数据操作,考虑分批处理以减少内存压力

结论

通过合理使用 LiteDB 的事务管理机制,可以确保数据的一致性和完整性,为应用程序提供可靠的数据持久化解决方案。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!