C# 上位机实战:用 LiteDB 构建本地测试数据管理系统

C# 上位机实战:用 LiteDB 构建本地测试数据管理系统

在上位机和桌面软件开发中,本地数据存储是必不可少的一环。

测试数据、原始采样、运行日志、配置状态......这些信息都需要可靠保存,同时又要方便读取、查询和归档。

很多开发者习惯用 SQLite,但在 C# 上位机项目中,我发现 LiteDB 更符合面向对象、单机轻量存储的需求。

本文带你一步步用 LiteDB 构建一个完整的 测试数据管理系统,从自动生成测试数据,到存储、查询、导出 Excel,再到批量删除和归档。


1. LiteDB 简介

LiteDB 是一个 纯 .NET 实现的嵌入式 NoSQL 数据库

  • 单文件 .db 存储数据,无需数据库服务
  • 面向对象,可直接存储 C# 类对象
  • 支持事务、索引、LINQ 查询
  • 部署简单,非常适合上位机和桌面软件

它更像一个 可安全持久化的对象集合,而不是传统关系型数据库。


2. 项目目标

  1. 自动生成测试数据
  2. 存入 LiteDB
  3. 支持条件查询
  4. 导出 Excel
  5. 批量删除与归档

3. 数据模型设计

csharp 复制代码
using LiteDB;
using System;
using System.Collections.Generic;

public class TestRecord
{
    public ObjectId Id { get; set; }
    public DateTime TestTime { get; set; }
    public string LotId { get; set; }
    public string DeviceId { get; set; }
    public bool Pass { get; set; }
    public Dictionary<string, double> TestItems { get; set; }
    public byte[] RawData { get; set; }
}
  • ObjectId:自动生成唯一 ID
  • TestItems:可灵活增减测试项
  • RawData:存储原始采样数据

4. 数据库初始化

csharp 复制代码
public class DatabaseService
{
    private readonly LiteDatabase _db;
    public ILiteCollection<TestRecord> Records { get; }

    public DatabaseService(string dbPath = "testdata.db")
    {
        _db = new LiteDatabase(dbPath);
        Records = _db.GetCollection<TestRecord>("records");

        // 创建索引
        Records.EnsureIndex(x => x.LotId);
        Records.EnsureIndex(x => x.TestTime);
        Records.EnsureIndex(x => x.Pass);
    }
}

自动创建数据库和集合,索引优化查询性能。


5. 自动生成测试数据

csharp 复制代码
public class TestDataGenerator
{
    private static Random _rand = new Random();

    public static TestRecord Generate(string lotId, string deviceId)
    {
        return new TestRecord
        {
            TestTime = DateTime.Now,
            LotId = lotId,
            DeviceId = deviceId,
            Pass = _rand.NextDouble() > 0.1,
            TestItems = new Dictionary<string, double>
            {
                { "Voltage", Math.Round(_rand.NextDouble() * 5, 2) },
                { "Current", Math.Round(_rand.NextDouble() * 2, 2) },
                { "Resistance", Math.Round(_rand.NextDouble() * 100, 2) }
            },
            RawData = new byte[100]
        };
    }
}

模拟上位机测试结果,90% 通过率。


6. 数据写入

csharp 复制代码
public class TestService
{
    private readonly DatabaseService _dbService;

    public TestService(DatabaseService dbService)
    {
        _dbService = dbService;
    }

    public void InsertTestRecord(TestRecord record)
    {
        _dbService.Records.Insert(record);
    }

    public void InsertTestBatch(IEnumerable<TestRecord> records)
    {
        _dbService.Records.InsertBulk(records);
    }
}

7. 查询数据

csharp 复制代码
public class QueryService
{
    private readonly DatabaseService _dbService;

    public QueryService(DatabaseService dbService)
    {
        _dbService = dbService;
    }

    public List<TestRecord> QueryByLot(string lotId)
        => _dbService.Records.Find(x => x.LotId == lotId).ToList();

    public List<TestRecord> QueryFailed()
        => _dbService.Records.Find(x => !x.Pass)
                             .OrderByDescending(x => x.TestTime)
                             .ToList();

    public List<TestRecord> QueryByDateRange(DateTime start, DateTime end)
        => _dbService.Records.Find(x => x.TestTime >= start && x.TestTime <= end).ToList();
}

8. 导出 Excel(ClosedXML)

csharp 复制代码
using ClosedXML.Excel;
using System.IO;

public class ExcelExporter
{
    public static void Export(List<TestRecord> records, string filePath)
    {
        using var wb = new XLWorkbook();
        var ws = wb.Worksheets.Add("TestData");

        ws.Cell(1, 1).Value = "Id";
        ws.Cell(1, 2).Value = "TestTime";
        ws.Cell(1, 3).Value = "LotId";
        ws.Cell(1, 4).Value = "DeviceId";
        ws.Cell(1, 5).Value = "Pass";
        ws.Cell(1, 6).Value = "TestItems";

        int row = 2;
        foreach (var r in records)
        {
            ws.Cell(row, 1).Value = r.Id.ToString();
            ws.Cell(row, 2).Value = r.TestTime;
            ws.Cell(row, 3).Value = r.LotId;
            ws.Cell(row, 4).Value = r.DeviceId;
            ws.Cell(row, 5).Value = r.Pass;
            ws.Cell(row, 6).Value = string.Join(";", r.TestItems.Select(kv => $"{kv.Key}:{kv.Value}"));
            row++;
        }

        wb.SaveAs(filePath);
    }
}

9. 批量删除与归档

csharp 复制代码
public class DataMaintenance
{
    private readonly DatabaseService _dbService;

    public DataMaintenance(DatabaseService dbService)
    {
        _dbService = dbService;
    }

    public void DeleteByLot(string lotId)
    {
        _dbService.Records.DeleteMany(x => x.LotId == lotId);
    }

    public void ArchiveOldData(DateTime beforeDate, string archiveDbPath)
    {
        var oldRecords = _dbService.Records.Find(x => x.TestTime < beforeDate).ToList();
        using var archiveDb = new LiteDatabase(archiveDbPath);
        archiveDb.GetCollection<TestRecord>("records").InsertBulk(oldRecords);

        _dbService.Records.DeleteMany(x => x.TestTime < beforeDate);
    }
}

10. 主程序示例

csharp 复制代码
class Program
{
    static void Main()
    {
        var dbService = new DatabaseService();
        var testService = new TestService(dbService);
        var queryService = new QueryService(dbService);

        // 生成 10 条测试数据
        var batch = Enumerable.Range(1, 10)
            .Select(i => TestDataGenerator.Generate("LOT202601", $"DEV{i:000}"))
            .ToList();

        testService.InsertTestBatch(batch);

        // 查询失败记录
        var failed = queryService.QueryFailed();
        Console.WriteLine($"Failed count: {failed.Count}");

        // 导出 Excel
        ExcelExporter.Export(batch, "TestData.xlsx");
        Console.WriteLine("Export done.");

        // 删除某批次数据
        var maintenance = new DataMaintenance(dbService);
        maintenance.DeleteByLot("LOT202601");
        Console.WriteLine("Batch deleted.");

        // 归档旧数据
        maintenance.ArchiveOldData(DateTime.Now.AddDays(-30), "archive.db");
        Console.WriteLine("Archive done.");
    }
}

11. 总结

  • LiteDB 完全贴合 C# 上位机项目:面向对象、灵活、轻量
  • 操作简洁:无需写 SQL,数据结构可灵活扩展
  • 完整流程可落地:生成 → 存储 → 查询 → 导出 → 删除/归档

对于本地测试数据管理、日志存储、原始采样数据等场景,LiteDB 是一个值得尝试的工具。

相关推荐
向上的车轮14 小时前
为什么.NET(C#)转 Java 开发时常常在“吐槽”Java:checked exception
java·c#·.net
island131414 小时前
CANN GE(图引擎)深度解析:计算图优化管线、内存静态规划与异构任务的 Stream 调度机制
开发语言·人工智能·深度学习·神经网络
坚持就完事了14 小时前
Java中的集合
java·开发语言
魔芋红茶14 小时前
Python 项目版本控制
开发语言·python
云小逸14 小时前
【nmap源码解析】Nmap OS识别核心模块深度解析:osscan2.cc源码剖析(1)
开发语言·网络·学习·nmap
冰暮流星14 小时前
javascript之二重循环练习
开发语言·javascript·数据库
风指引着方向14 小时前
自定义算子开发入门:基于 CANN op-plugin 的扩展实践
开发语言
Fairy要carry14 小时前
面试-GRPO强化学习
开发语言·人工智能
Liekkas Kono14 小时前
RapidOCR Python 贡献指南
开发语言·python·rapidocr
张张努力变强14 小时前
C++ STL string 类:常用接口 + auto + 范围 for全攻略,字符串操作效率拉满
开发语言·数据结构·c++·算法·stl