2025-11-09
LiteDB
00

目录

主要特点
环境准备
核心代码实现
数据模型定义
数据库链接
数据访问层实现
告警管理实现
数据采集服务实现
使用示例
性能优化建议
总结

本文介绍如何使用C#和LiteDB实现一个轻量级的工业设备数据记录系统。LiteDB是一个开源的NoSQL嵌入式数据库,类似于MongoDB,但更轻量级,非常适合用于小型工业设备数据采集场景。

主要特点

  • 单文件数据库,无需安装配置
  • 支持ACID事务
  • 支持文档存储和索引
  • 跨平台,可在Windows/Linux/MacOS上运行
  • 性能优秀,适合工业现场数据采集

环境准备

Bash
# 通过NuGet安装LiteDB包 Install-Package LiteDB

image.png

核心代码实现

数据模型定义

C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LiteDB; namespace App15 { // 设备数据模型 public class DeviceData { public ObjectId Id { get; set; } // 文档ID public string DeviceId { get; set; } // 设备ID public DateTime Timestamp { get; set; } // 时间戳 public double Temperature { get; set; } // 温度 public double Humidity { get; set; } // 湿度 public double Pressure { get; set; } // 压力 public string Status { get; set; } // 设备状态 } }
C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LiteDB; namespace App15 { // 设备告警模型 public class DeviceAlarm { public ObjectId Id { get; set; } public string DeviceId { get; set; } public DateTime AlarmTime { get; set; } public string AlarmType { get; set; } public string AlarmMessage { get; set; } public bool IsHandled { get; set; } } }

数据库链接

C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LiteDB; namespace App15 { public class DatabaseConfig { public static ConnectionString GetSharedConnectionString(string dbPath) { return new ConnectionString { Filename = dbPath, Connection= LiteDB.ConnectionType.Shared,//这里很重要,默认是独享的 }; } } }

数据访问层实现

C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LiteDB; namespace App15 { public class DeviceDataRepository { private readonly string _dbPath; private readonly string _collectionName; public DeviceDataRepository(string dbPath, string collectionName) { _dbPath = dbPath; _collectionName = collectionName; } // 插入单条数据 public void Insert(DeviceData data) { using (var db = new LiteDatabase(DatabaseConfig.GetSharedConnectionString(_dbPath))) { var collection = db.GetCollection<DeviceData>(_collectionName); collection.Insert(data); } } // 批量插入数据 public void InsertBatch(IEnumerable<DeviceData> dataList) { using (var db = new LiteDatabase(DatabaseConfig.GetSharedConnectionString(_dbPath))) { var collection = db.GetCollection<DeviceData>(_collectionName); collection.InsertBulk(dataList); } } // 查询指定时间范围的数据 public IEnumerable<DeviceData> QueryByTimeRange(DateTime startTime, DateTime endTime) { using (var db = new LiteDatabase(DatabaseConfig.GetSharedConnectionString(_dbPath))) { var collection = db.GetCollection<DeviceData>(_collectionName); return collection.Find(x => x.Timestamp >= startTime && x.Timestamp <= endTime); } } // 查询指定设备的最新数据 public DeviceData GetLatestData(string deviceId) { using (var db = new LiteDatabase(DatabaseConfig.GetSharedConnectionString(_dbPath))) { var collection = db.GetCollection<DeviceData>(_collectionName); return collection.FindOne(Query.All(Query.Descending)); } } // 删除过期数据 public int DeleteOldData(DateTime beforeTime) { using (var db = new LiteDatabase(DatabaseConfig.GetSharedConnectionString(_dbPath))) { var collection = db.GetCollection<DeviceData>(_collectionName); return collection.DeleteMany(x => x.Timestamp < beforeTime); } } } }

告警管理实现

C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LiteDB; namespace App15 { public class AlarmManager { private readonly string _dbPath; private readonly string _collectionName = "device_alarms"; public AlarmManager(string dbPath) { _dbPath = dbPath; } // 创建告警 public void CreateAlarm(DeviceAlarm alarm) { using (var db = new LiteDatabase(DatabaseConfig.GetSharedConnectionString(_dbPath))) { var collection = db.GetCollection<DeviceAlarm>(_collectionName); collection.Insert(alarm); } } // 获取未处理的告警 public IEnumerable<DeviceAlarm> GetUnhandledAlarms() { using (var db = new LiteDatabase(DatabaseConfig.GetSharedConnectionString(_dbPath))) { var collection = db.GetCollection<DeviceAlarm>(_collectionName); return collection.Find(x => !x.IsHandled); } } // 标记告警为已处理 public bool HandleAlarm(ObjectId alarmId) { using (var db = new LiteDatabase(DatabaseConfig.GetSharedConnectionString(_dbPath))) { var collection = db.GetCollection<DeviceAlarm>(_collectionName); var alarm = collection.FindById(alarmId); if (alarm != null) { alarm.IsHandled = true; return collection.Update(alarm); } return false; } } } }

数据采集服务实现

C#
public class DataCollectionService { private readonly DeviceDataRepository _repository; private readonly AlarmManager _alarmManager; private readonly Timer _timer; private readonly string _deviceId; public DataCollectionService(string dbPath, string deviceId) { _repository = new DeviceDataRepository(dbPath, "device_data"); _alarmManager = new AlarmManager(dbPath); _deviceId = deviceId; // 创建定时器,每5秒采集一次数据 _timer = new Timer(CollectData, null, TimeSpan.Zero, TimeSpan.FromSeconds(5)); } private void CollectData(object state) { try { // 模拟从设备读取数据 var data = ReadDeviceData(); // 存储数据 _repository.Insert(data); // 检查是否需要产生告警 CheckAlarmConditions(data); } catch (Exception ex) { // 记录异常 Console.WriteLine($"数据采集异常: {ex.Message}"); } } private DeviceData ReadDeviceData() { // 这里模拟从实际设备读取数据 // 实际应用中需要替换为真实的设备通信代码 Random rand = new Random(); return new DeviceData { DeviceId = _deviceId, Timestamp = DateTime.Now, Temperature = 20 + rand.NextDouble() * 10, Humidity = 40 + rand.NextDouble() * 20, Pressure = 101 + rand.NextDouble() * 2, Status = "Running" }; } private void CheckAlarmConditions(DeviceData data) { // 检查温度是否超过阈值 if (data.Temperature > 28) { _alarmManager.CreateAlarm(new DeviceAlarm { DeviceId = data.DeviceId, AlarmTime = DateTime.Now, AlarmType = "HighTemperature", AlarmMessage = $"温度过高: {data.Temperature:F2}°C", IsHandled = false }); } // 检查湿度是否超过阈值 if (data.Humidity > 55) { _alarmManager.CreateAlarm(new DeviceAlarm { DeviceId = data.DeviceId, AlarmTime = DateTime.Now, AlarmType = "HighHumidity", AlarmMessage = $"湿度过高: {data.Humidity:F2}%", IsHandled = false }); } } }

使用示例

C#
class Program { static void Main(string[] args) { string dbPath = "DeviceData.db"; string deviceId = "Device001"; // 启动数据采集服务 var dataCollectionService = new DataCollectionService(dbPath, deviceId); // 创建数据访问对象 var repository = new DeviceDataRepository(dbPath, "device_data"); var alarmManager = new AlarmManager(dbPath); // 演示查询最近1小时的数据 var endTime = DateTime.Now; var startTime = endTime.AddHours(-1); var recentData = repository.QueryByTimeRange(startTime, endTime); foreach (var data in recentData) { Console.WriteLine($"时间: {data.Timestamp}, 温度: {data.Temperature:F2}°C, " + $"湿度: {data.Humidity:F2}%, 压力: {data.Pressure:F2}kPa"); } // 查看未处理的告警 var unhandledAlarms = alarmManager.GetUnhandledAlarms(); foreach (var alarm in unhandledAlarms) { Console.WriteLine($"告警时间: {alarm.AlarmTime}, 类型: {alarm.AlarmType}, " + $"消息: {alarm.AlarmMessage}"); } Console.WriteLine("按任意键退出..."); Console.ReadKey(); } }

image.png

性能优化建议

批量插入:当需要插入大量数据时,使用InsertBulk而不是单条插入。

索引优化:为常用查询字段创建索引:

C#
collection.EnsureIndex(x => x.DeviceId); collection.EnsureIndex(x => x.Timestamp);

定期清理:实现数据清理策略,定期删除过期数据:

C#
// 删除30天前的数据 repository.DeleteOldData(DateTime.Now.AddDays(-30));

连接复用:对于高频操作,考虑复用数据库连接:

C#
public class OptimizedRepository { private readonly LiteDatabase _db; public OptimizedRepository(string dbPath) { _db = new LiteDatabase(dbPath); } public void Dispose() { _db?.Dispose(); } }

总结

本文介绍了如何使用LiteDB实现一个简单但完整的工业设备数据记录系统。该系统具有以下特点:

  • 支持实时数据采集和存储
  • 提供灵活的数据查询功能
  • 包含基本的告警管理
  • 性能优化和数据清理机制

LiteDB的优势在于其简单性和可靠性,非常适合小型工业现场的数据采集需求。通过合理的架构设计和优化,可以构建出一个高效、可靠的数据记录系统。

本文作者:技术老小子

本文链接:

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