前言原单库版本拆分双存储职责,适配业务需求上面的可视化架构图帮你快速理解整个设计的核心思路:一句话总结:把"容易丢、要速度"的日志交给本地 SQLite,把"要共享、要统计"的工单交给服务端 MySQL,两者通过Service 接口层完全解耦,ViewModel 里一行 SQL 都没有。一、项目基础信息1. 目标框架TargetFrameworknet6.0-windows/TargetFramework UseWPFtrue/UseWPF2. 完整 NuGet 包清单(固定版本,一键批量安装)NuGet 控制台批量指令# MVVM核心 Install-Package CommunityToolkit.Mvvm -Version 8.2.2 # DI容器 Install-Package Microsoft.Extensions.DependencyInjection -Version 8.0.1 # EF Core核心 Install-Package Microsoft.EntityFrameworkCore -Version 8.0.1 # SQLite本地日志库 Install-Package Microsoft.EntityFrameworkCore.Sqlite -Version 8.0.1 # MySQL生产业务库 Install-Package Pomelo.EntityFrameworkCore.MySql -Version 8.0.1 # EF迁移工具 Install-Package Microsoft.EntityFrameworkCore.Tools -Version 8.0.1csproj 包引用片段ItemGroup PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" / PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" / PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.1" / PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.1" / PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.1" / PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.1" PrivateAssets="all" / /ItemGroup二、五层架构总览(双数据库改造点标注)基于 3 台量产龙门贴片机实战沉淀分层架构,严格遵循上层依赖下层,下层禁止反向依赖,Service 层通过回调 / 事件上报状态解耦循环依赖。目录结构(新增数据库相关目录)SMTMachineDemo/ ├─ HAL/ # 雷赛运动卡原生封装 │ └─ Dmc3000Native.cs ├─ Core/ │ ├─ Calibration/ # 九点标定算法 │ │ └─ MatrixTransform.cs │ ├─ DbContext/ # 双数据库上下文 │ │ ├─ SqliteLogDbContext.cs │ │ └─ MysqlProductionDbContext.cs │ └─ Entity/ # 双库实体 │ ├─ LogRecord.cs # SQLite日志表实体 │ └─ ProductionBatch.cs # MySQL生产批次实体 ├─ Models/ # 硬件状态数据模型 │ ├─ AxisStatus.cs │ └─ AxisStatusEventArgs.cs ├─ Services/ │ ├─ Interfaces/ │ │ ├─ IMotionService.cs │ │ ├─ ICameraService.cs │ │ ├─ ILogService.cs # 日志服务接口(SQLite实现) │ │ └─ IProductionService.cs # 生产数据接口(MySQL实现) │ ├─ MockMotionService.cs │ ├─ MockCameraService.cs │ ├─ MockLogService.cs # 内存模拟日志(无数据库演示) │ ├─ SqliteLogService.cs # SQLite持久化日志实现 │ ├─ MockProductionService.cs # 模拟生产数据 │ └─ MysqlProductionService.cs # MySQL真实生产库实现 ├─ ViewModels/ │ ├─ ViewModelBase.cs │ └─ MainViewModel.cs ├─ Converters/ │ └─ CollectionToStringConverter.cs ├─ App.xaml ├─ App.xaml.cs # DI注册双数据库、模拟/真机切换 └─ MainWindow.xaml三、分层完整可运行源码3.1 Core 数据库实体 DbContextCore/Entity/LogRecord.cs(SQLite 本地日志表)using Microsoft.EntityFrameworkCore; using System.ComponentModel.DataAnnotations; namespace SMTMachineDemo.Core.Entity; /// summary /// SQLite本地日志记录实体,断电不丢失 /// /summary [Index(nameof(CreateTime))] public class LogRecord { [Key] public long Id { get; set; } /// summary日志内容/summary public string Content { get; set; } = string.Empty; /// summary记录时间戳/summary public DateTime CreateTime { get; set; } /// summary日志等级:Info/Warn/Error/summary public string LogLevel { get; set; } = "Info"; }Core/Entity/ProductionBatch.cs(MySQL 生产工单批次)using Microsoft.EntityFrameworkCore; using System.ComponentModel.DataAnnotations; namespace SMTMachineDemo.Core.Entity; /// summary /// MySQL生产批次工单,多设备共享统计 /// /summary [Index(nameof(BatchNo), IsUnique = true)] [Index(nameof(ProduceStartTime))] public class ProductionBatch { [Key] public long Id { get; set; } /// summary生产批次号/summary [MaxLength(64)] public string BatchNo { get; set; } = string.Empty; /// summary产品型号/summary [MaxLength(128)] public string ProductModel { get; set; } = string.Empty; /// summary计划产量/summary public int PlanCount { get; set; } /// summary实际完成产量/summary public int ActualCount { get; set; } /// summary不良品数量/summary public int DefectCount { get; set; } /// summary生产开始时间/summary public DateTime ProduceStartTime { get; set; } /// summary生产结束时间/summary public DateTime? ProduceEndTime { get; set; } /// summary设备编号/summary [MaxLength(32)] public string DeviceSn { get; set; } = string.Empty; }Core/DbContext/SqliteLogDbContext.csusing Microsoft.EntityFrameworkCore; using SMTMachineDemo.Core.Entity; namespace SMTMachineDemo.Core.DbContext; /// summary /// SQLite本地日志数据库上下文 /// /summary public class SqliteLogDbContext : Microsoft.EntityFrameworkCore.DbContext { public DbSetLogRecord LogRecords { get; set; } = null!; private readonly string _connectionString; public SqliteLogDbContext(DbContextOptionsSqliteLogDbContext options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { // 日志表按时间自动清理旧数据(保留30天) modelBuilder.EntityLogRecord() .HasData(); } }Core/DbContext/MysqlProductionDbContext.csusing Microsoft.EntityFrameworkCore; using SMTMachineDemo.Core.Entity; namespace SMTMachineDemo.Core.DbContext; /// summary /// MySQL服务端生产业务数据库上下文 /// /summary public class MysqlProductionDbContext : Microsoft.EntityFrameworkCore.DbContext { public DbSetProductionBatch ProductionBatches { get; set; } = null!; public MysqlProductionDbContext(DbContextOptionsMysqlProductionDbContext options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { // MySQL字符集、排序规则配置 modelBuilder.EntityProductionBatch() .Property(x = x.BatchNo) .HasColumnType("varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); } }Core/Calibration/MatrixTransform.cs(原有标定算法不变)namespace SMTMachineDemo.Core.Calibration; public static class PixelToMechanical { /// summary /// 九点标定仿射变换,像素坐标转机械轴坐标 /// /summary public static (double x, double y) Transform( double pixelX, double pixelY,