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

整合 Sugar ORM 连接 SQLite 数据库到 WPF 折线图项目

一、核心目标

在原有 WPF 折线图项目基础上,通过Sugar ORM连接 SQLite 数据库,实现:

  1. 从 SQLite 读取历史销量数据渲染折线图

  2. 追加数据时同时写入数据库,实现数据持久化

二、前置准备

1. 安装依赖包

通过 NuGet 安装以下包:

包名作用
SqlSugarCoreSugar ORM 核心(支持 SQLite)
System.Data.SQLiteSQLite 数据库驱动
Microsoft.Data.Sqlite可选(替代 System.Data.SQLite)

2. SQLite 数据库准备

(1)创建数据库文件

在项目根目录创建SalesData.db文件(也可让 Sugar 自动创建)。

(2)创建销量表

定义销量实体类,Sugar 会自动生成数据表:

using SqlSugar; using System; ​ namespace LineChart2.Model { /// <summary> /// 销量数据表实体 /// </summary> [SugarTable("SalesRecord")] public class SalesRecord { /// <summary> /// 主键(自增) /// </summary> [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } ​ /// <summary> /// 年份(2023/2024) /// </summary> [SugarColumn(ColumnName = "Year")] public int SalesYear { get; set; } ​ /// <summary> /// 月份(1-12) /// </summary> public int Month { get; set; } ​ /// <summary> /// 销量数值 /// </summary> public double SalesValue { get; set; } ​ /// <summary> /// 创建时间 /// </summary> public DateTime CreateTime { get; set; } = DateTime.Now; } }

三、Sugar ORM 初始化配置

创建数据库帮助类,封装 Sugar 连接和操作:

using SqlSugar; using LineChart2.Model; using System; using System.IO; ​ namespace LineChart2.Helper { public class DbHelper { // Sugar数据库连接实例(单例) public static SqlSugarClient Db { get; private set; } ​ static DbHelper() { // 初始化连接 InitDb(); } ​ /// <summary> /// 初始化SQLite连接 /// </summary> private static void InitDb() { // 获取数据库文件路径(项目根目录) string dbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SalesData.db"); ​ Db = new SqlSugarClient(new ConnectionConfig { ConnectionString = $"Data Source={dbPath};", // SQLite连接字符串 DbType = DbType.Sqlite, // 数据库类型 IsAutoCloseConnection = true, // 自动关闭连接 InitKeyType = InitKeyType.Attribute // 从特性读取主键/自增配置 }); ​ // 初始化数据表(不存在则创建) Db.CodeFirst.InitTables(typeof(SalesRecord)); ​ // 开启日志(调试用,生产可关闭) Db.Aop.OnLogExecuting = (sql, pars) => { Console.WriteLine($"SQL:{sql} \r\n参数:{string.Join(",", pars.Select(p => p.ParameterName + "=" + p.Value))}"); }; } ​ #region 销量数据操作封装 /// <summary> /// 批量插入销量数据 /// </summary> public static void BatchInsertSalesData(SalesRecord[] records) { Db.Insertable(records).ExecuteCommand(); } ​ /// <summary> /// 插入单条销量数据 /// </summary> public static int InsertSalesData(SalesRecord record) { return Db.Insertable(record).ExecuteReturnIdentity(); } ​ /// <summary> /// 根据年份查询销量数据 /// </summary> public static List<SalesRecord> GetSalesDataByYear(int year) { return Db.Queryable<SalesRecord>() .Where(r => r.SalesYear == year) .OrderBy(r => r.Month) .ToList(); } ​ /// <summary> /// 查询所有年份的销量数据 /// </summary> public static List<SalesRecord> GetAllSalesData() { return Db.Queryable<SalesRecord>() .OrderBy(r => r.SalesYear) .ThenBy(r => r.Month) .ToList(); } #endregion } }

四、修改折线图控件,整合数据库操作

1. 重构 UCLineChart.xaml.cs

替换原有硬编码数据,改为从数据库读取 / 写入:

using LiveCharts; using LiveCharts.Defaults; using LiveCharts.Wpf; using LineChart2.Helper; using LineChart2.Model; using System; using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Media; ​ namespace LineChart2 { public partial class UCLineChart : UserControl { public SeriesCollection SeriesCollection { get; set; } public string[] Labels { get; set; } public Func<double, string> YFormatter { get; set; } ​ // 模拟销量数据 private readonly Random _random = new Random(); // 当前最大月份(用于追加数据) private int _currentMaxMonth = 5; ​ public UCLineChart() { InitializeComponent(); ​ // 初始化图表数据(优先从数据库读取) InitChartDataFromDb(); ​ // Y轴格式化(显示整数) YFormatter = value => $"{value:N0}"; ​ DataContext = this; } ​ /// <summary> /// 从数据库初始化图表数据 /// </summary> private void InitChartDataFromDb() { SeriesCollection = new SeriesCollection(); ​ // 1. 查询所有销量数据 var allSalesData = DbHelper.GetAllSalesData(); ​ // 2. 如果数据库无数据,初始化默认数据并写入数据库 if (!allSalesData.Any()) { InitDefaultDataAndWriteToDb(); allSalesData = DbHelper.GetAllSalesData(); } ​ // 3. 按年份分组构建折线系列 var groupedData = allSalesData.GroupBy(r => r.SalesYear); foreach (var group in groupedData) { int year = group.Key; var values = group.OrderBy(r => r.Month).Select(r => r.SalesValue).ToList(); ​ // 创建折线系列 LineSeries series = new LineSeries { Title = $"{year}年", Values = new ChartValues<double>(values), LineSmoothness = 0.3, StrokeThickness = 2, PointGeometrySize = 8 }; ​ // 不同年份设置不同颜色 series.Stroke = year == 2024 ? Brushes.DodgerBlue : Brushes.OrangeRed; series.PointForeground = year == 2024 ? Brushes.DodgerBlue : Brushes.OrangeRed; series.PointGeometry = year == 2024 ? DefaultGeometries.Circle : DefaultGeometries.Square; ​ SeriesCollection.Add(series); } ​ // 4. 构建X轴标签(1-当前最大月份) _currentMaxMonth = allSalesData.Max(r => r.Month); Labels = Enumerable.Range(1, _currentMaxMonth).Select(m => $"{m}月").ToArray(); } ​ /// <summary> /// 初始化默认数据并写入数据库 /// </summary> private void InitDefaultDataAndWriteToDb() { List<SalesRecord> defaultData = new List<SalesRecord>(); ​ // 2024年1-5月数据 double[] sales2024 = { 120, 150, 110, 180, 160 }; for (int i = 0; i < sales2024.Length; i++) { defaultData.Add(new SalesRecord { SalesYear = 2024, Month = i + 1, SalesValue = sales2024[i] }); } ​ // 2023年1-5月数据 double[] sales2023 = { 100, 130, 140, 150, 130 }; for (int i = 0; i < sales2023.Length; i++) { defaultData.Add(new SalesRecord { SalesYear = 2023, Month = i + 1, SalesValue = sales2023[i] }); } ​ // 批量写入数据库 DbHelper.BatchInsertSalesData(defaultData.ToArray()); } ​ // 追加数据按钮点击事件 private void BtnAddData_Click(object sender, RoutedEventArgs e) { // 1. 月份+1 _currentMaxMonth++; int newMonth = _currentMaxMonth; ​ // 2. 生成随机销量(100-200) double sales2024 = _random.Next(100, 200); double sales2023 = _random.Next(100, 200); ​ // 3. 写入数据库 DbHelper.InsertSalesData(new SalesRecord { SalesYear = 2024, Month = newMonth, SalesValue = sales2024 }); DbHelper.InsertSalesData(new SalesRecord { SalesYear = 2023, Month = newMonth, SalesValue = sales2023 }); ​ // 4. 追加数据点到图表 SeriesCollection[0].Values.Add(sales2024); SeriesCollection[1].Values.Add(sales2023); ​ // 5. 更新X轴标签 Array.Resize(ref Labels, Labels.Length + 1); Labels[Labels.Length - 1] = $"{newMonth}月"; ​ // 6. 刷新绑定(触发UI更新) chart.AxisX[0].Labels = Labels; ​ // 更新按钮文本(追加7月、8月...) (sender as Button).Content = $"追加{newMonth + 1}月数据"; } } }

2. 修复原代码 Bug

原代码中Labels数组扩容时使用了错误的方法,已替换为Array.Resize

// 错误写法 // Labels[Labels.Length - 1] = "6月"; ​ // 正确写法 Array.Resize(ref Labels, Labels.Length + 1); Labels[Labels.Length - 1] = $"{newMonth}月";

五、关键功能说明

1. 数据库初始化逻辑

  • 首次运行时,若数据库无数据,自动插入 2023/2024 年 1-5 月默认数据

  • 后续运行时,从数据库读取数据渲染图表,保证数据持久化

2. 数据追加逻辑

  • 点击按钮时,生成随机销量数据并写入数据库

  • 同时更新图表数据,实现 “数据库 + UI” 双向同步

  • 按钮文本动态更新(追加 6 月→追加 7 月→...)

3. Sugar ORM 核心操作

操作核心代码示例
初始化连接new SqlSugarClient(new ConnectionConfig { ... })
自动建表Db.CodeFirst.InitTables(typeof(SalesRecord))
批量插入Db.Insertable(records).ExecuteCommand()
条件查询Db.Queryable<SalesRecord>().Where(r => r.SalesYear == year).ToList()
排序查询OrderBy(r => r.Month)

六、运行验证

  1. 启动项目,首次运行会自动创建SalesData.db文件,并插入默认数据

  2. 图表会显示 2023/2024 年 1-5 月销量折线

  3. 点击 “追加 6 月数据” 按钮:

    • 数据库会新增 2023/2024 年 6 月销量记录

    • 图表自动追加 6 月数据点,X 轴标签更新为 “6 月”

    • 按钮文本变为 “追加 7 月数据”,重复点击可持续追加

七、扩展优化建议

1. 异常处理

添加 try-catch 捕获数据库操作异常:

try { DbHelper.InsertSalesData(new SalesRecord { ... }); } catch (Exception ex) { MessageBox.Show($"数据写入失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); }

2. 分页查询(大数据量)

若销量数据量大,可分页读取:

// 分页查询2024年数据(第1页,每页10条) var pageData = Db.Queryable<SalesRecord>() .Where(r => r.SalesYear == 2024) .OrderBy(r => r.Month) .ToPageList(1, 10);

3. 数据更新 / 删除

扩展 DbHelper 添加更新 / 删除方法:

/// <summary> /// 更新销量数据 /// </summary> public static bool UpdateSalesData(SalesRecord record) { return Db.Updateable(record).ExecuteCommand() > 0; } ​ /// <summary> /// 删除指定月份数据 /// </summary> public static bool DeleteSalesData(int year, int month) { return Db.Deleteable<SalesRecord>() .Where(r => r.SalesYear == year && r.Month == month) .ExecuteCommand() > 0; }

4. 多表关联(进阶)

若需要关联其他表(如产品表),可使用 Sugar 的联表查询:

// 关联产品表查询销量 var joinData = Db.Queryable<SalesRecord, Product>((s, p) => new JoinQueryInfos( JoinType.Inner, s.ProductId == p.Id)) .Select((s, p) => new { s.Month, s.SalesValue, p.ProductName }) .ToList();

八、项目结构梳理

LineChart2/ ├─ Helper/ │ └─ DbHelper.cs // Sugar ORM数据库操作封装 ├─ Model/ │ └─ SalesRecord.cs // 销量数据实体类 ├─ UCLineChart.xaml // 折线图用户控件XAML ├─ UCLineChart.xaml.cs // 折线图逻辑(整合数据库) ├─ MainWindow.xaml // 主窗口 └─ SalesData.db // SQLite数据库文件(运行后生成)

通过以上改造,原有的 WPF 折线图项目实现了与 SQLite 数据库的无缝整合,数据不再局限于内存,而是通过 Sugar ORM 实现了持久化存储和动态读写。

http://www.jsqmd.com/news/192752/

相关文章:

  • Chrome、Edge用户注意!HeyGem系统浏览器兼容性说明
  • 怒族仙女节庆祝:姑娘数字人跳起传统舞蹈
  • 2025年艺术漆代理头部品牌推荐,最新测评精选代理品牌指南 - myqiye
  • 一键打包下载功能来了!HeyGem批量生成后如何导出所有视频
  • 揭秘PHP如何高效对接MQTT协议:实现物联网网关实时通信的关键技术
  • 羌语碉楼建造技艺:工匠数字人还原古代建筑智慧
  • 【PHP图像识别API对接实战】:手把手教你快速集成高精度识别功能
  • C#跨平台调试生死线,拦截器日志追踪的3步精准定位法
  • CUDA与cuDNN配置指南:为HeyGem系统启用深度学习推理支持
  • 鄂温克语驯鹿养殖:猎人数字人传授饲养经验
  • 紧急!未加密的灯光控制接口正在泄露用户隐私:PHP安全加固指南
  • 讯飞语音API vs 本地TTS:哪种更适合喂给HeyGem系统?
  • xhEditor ppt导入支持音频和视频
  • 2025安徽家政服务公司TOP5权威推荐:赛瑞斯与竞争对手相比优势在哪 - myqiye
  • xhEditor粘贴微信公众号内容到html
  • C# AOP拦截器跨平台调试实战(从原理到部署的完整路径)
  • 柯尔克孜语玛纳斯史诗传唱:艺人数字人吟诵英雄传奇
  • 为什么顶尖团队都在用Span?,揭秘高性能库背后的秘密武器
  • xhEditor pdf导入识别图片和图表
  • 塔吉克族鹰舞表演:演员数字人展翅飞翔
  • GitHub镜像网站推荐 + HeyGem系统部署:加速开源项目落地
  • PHP 8.7即将上线:现在不看这份基准报告就晚了!
  • 普米语韩规节祭祀:祭司数字人带领族群缅怀祖先
  • 如何用Swoole+Consul实现PHP高性能服务注册?(实战代码曝光)
  • 西门子 S7 PLC 通信 WPF 应用分析笔记
  • 塞浦路斯语婚礼习俗讲解:长辈数字人传授传统仪式细节
  • 格鲁吉亚语高加索登山指南:向导数字人介绍徒步路线
  • 为什么顶级公司都在测试PHP 8.7?(内部基准数据首次曝光)
  • 服务注册突然失效?PHP微服务容灾机制紧急应对指南
  • PHP WebSocket 实时消息推送全解析(从入门到高并发架构设计)