前一篇文章介绍MasterMemory,这个组件讨论的网友挺多了,有网友单独问我,说想用这个替换sqlite,我肯定是不支持的,虽然官方对比sqlite的性能与存储提示不少,但绝对不是db的读取逻辑。所以有了这篇文章,按网友说他现在30w数据在sqlite中大该150M,我模拟写了以下程序,试了一下,30万条设备数据,复杂的多维度筛选,用户输入关键词的瞬间就能看到结果。至于大家用在什么场景还是自己拿主义了。
作为C#开发者,你是否遇到过这些痛点:

C#// 传统方式:每次查询都要访问数据库
var result = dbContext.Equipment
.Where(e => e.Status == EquipmentStatus.Running)
.Where(e => e.Zone == selectedZone)
.ToList(); // 耗时:100-500ms
问题显而易见:
C#[MemoryTable("equipment"), MessagePackObject(true)]
public record Equipment
{
[PrimaryKey]
public required int EquipmentId { get; init; }
[SecondaryKey(0)]
public required string EquipmentCode { get; init; }
// 复合索引:区域+功率等级
[SecondaryKey(1, keyOrder: 0), NonUnique]
public required FactoryZone Zone { get; init; }
[SecondaryKey(1, keyOrder: 1), NonUnique]
public required int PowerLevel { get; init; }
[SecondaryKey(2), NonUnique]
public required EquipmentStatus Status { get; init; }
public required string Name { get; init; }
public required double Temperature { get; init; }
// ... 其他字段
}
🔥 设计亮点:
record类型确保不可变性和高性能C#public class EquipmentService
{
private MemoryDatabase _database;
// 🚀 毫秒级状态查询
public IEnumerable<Equipment> GetEquipmentByStatus(EquipmentStatus status)
{
return _database.EquipmentTable.FindByStatus(status);
}
// 🔍 复合索引查询:区域+功率
public IEnumerable<Equipment> GetEquipmentByZoneAndPower(
FactoryZone zone, int powerLevel)
{
return _database.EquipmentTable
.FindByZoneAndPowerLevel((zone, powerLevel));
}
// 📈 范围查询优化
public IEnumerable<Equipment> GetByPowerRange(int min, int max)
{
return _database.EquipmentTable
.FindRangeByPowerLevel(min, max);
}
}
构建一个管理30万台工业设备的实时监控系统:
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AppMasterMemoryTest.Models;
namespace AppMasterMemoryTest.Services
{
public class DataPersistenceService
{
private readonly string _dataDirectory;
private readonly string _databasePath;
private readonly Random _random;
public DataPersistenceService(string dataDirectory = "Data")
{
_dataDirectory = dataDirectory;
_databasePath = Path.Combine(_dataDirectory, "equipment_database.bin");
_random = new Random();
// 确保数据目录存在
if (!Directory.Exists(_dataDirectory))
{
Directory.CreateDirectory(_dataDirectory);
}
}
/// <summary>
/// 保存数据库到文件
/// </summary>
public async Task SaveDatabaseAsync(MemoryDatabase database)
{
try
{
// 获取数据库的二进制数据
var builder = new DatabaseBuilder();
builder.Append(database.EquipmentTable.All.ToArray());
byte[] databaseBinary = builder.Build();
// 异步写入文件
await File.WriteAllBytesAsync(_databasePath, databaseBinary);
}
catch (Exception ex)
{
throw new InvalidOperationException($"保存数据库失败: {ex.Message}", ex);
}
}
/// <summary>
/// 从文件加载数据库
/// </summary>
public async Task<MemoryDatabase> LoadDatabaseAsync()
{
try
{
if (!File.Exists(_databasePath))
{
throw new FileNotFoundException("数据库文件不存在");
}
// 异步读取文件
byte[] databaseBinary = await File.ReadAllBytesAsync(_databasePath);
return new MemoryDatabase(databaseBinary);
}
catch (Exception ex)
{
throw new InvalidOperationException($"加载数据库失败: {ex.Message}", ex);
}
}
/// <summary>
/// 检查数据库文件是否存在
/// </summary>
public bool DatabaseExists()
{
return File.Exists(_databasePath);
}
/// <summary>
/// 获取数据库文件大小(MB)
/// </summary>
public double GetDatabaseSize()
{
if (!File.Exists(_databasePath))
return 0;
var fileInfo = new FileInfo(_databasePath);
return fileInfo.Length / (1024.0 * 1024.0);
}
/// <summary>
/// 生成测试数据
/// </summary>
public async Task<MemoryDatabase> GenerateTestDataAsync(int count = 300000)
{
var equipment = new List<Equipment>();
var manufacturers = new[] { "西门子", "ABB", "施耐德", "三菱", "欧姆龙", "霍尼韦尔", "艾默生", "罗克韦尔" };
var equipmentTypes = Enum.GetValues<EquipmentType>();
var statuses = Enum.GetValues<EquipmentStatus>();
var zones = Enum.GetValues<FactoryZone>();
return await Task.Run(() =>
{
for (int i = 0; i < count; i++)
{
var type = equipmentTypes[_random.Next(equipmentTypes.Length)];
var status = statuses[_random.Next(statuses.Length)];
var zone = zones[_random.Next(zones.Length)];
var manufacturer = manufacturers[_random.Next(manufacturers.Length)];
var installDate = DateTime.Now.AddDays(-_random.Next(1, 3650)); // 1-10年前安装
var lastMaintenance = installDate.AddDays(_random.Next(1, (DateTime.Now - installDate).Days));
equipment.Add(new Equipment
{
EquipmentId = i,
EquipmentCode = $"{GetZoneCode(zone)}-{GetTypeCode(type)}-{i:D6}",
Name = $"{GetTypeName(type)}-{i:D4}",
Type = type,
Status = status,
Zone = zone,
PowerLevel = _random.Next(1, 1001), // 1-1000kW
Manufacturer = manufacturer,
Model = $"Model-{type}-{_random.Next(100, 999)}",
InstallDate = installDate,
LastMaintenanceDate = lastMaintenance,
OperatingHours = _random.NextDouble() * 50000, // 0-50000小时
Temperature = GenerateRealisticTemperature(status),
Pressure = GenerateRealisticPressure(type),
Vibration = GenerateRealisticVibration(status),
Remarks = _random.Next(10) < 2 ? GenerateRandomRemark() : null // 20%概率有备注
});
// 每10000条数据报告一次进度
if (i % 10000 == 0 && i > 0)
{
// 这里可以添加进度报告逻辑
}
}
var builder = new DatabaseBuilder();
builder.Append(equipment.ToArray());
byte[] databaseBinary = builder.Build();
return new MemoryDatabase(databaseBinary);
});
}
/// <summary>
/// 导出数据到CSV文件
/// </summary>
public async Task ExportToCsvAsync(MemoryDatabase database, string filePath)
{
var equipment = database.EquipmentTable.All.ToList();
var lines = new List<string>
{
"设备ID,设备编号,设备名称,设备类型,设备状态,工厂区域,功率等级,制造商,型号,安装日期,最后维护日期,运行小时数,温度,压力,振动值,备注"
};
lines.AddRange(equipment.Select(e =>
$"{e.EquipmentId},{e.EquipmentCode},{e.Name},{GetTypeName(e.Type)},{GetStatusName(e.Status)}," +
$"{GetZoneName(e.Zone)},{e.PowerLevel},{e.Manufacturer},{e.Model}," +
$"{e.InstallDate:yyyy-MM-dd},{e.LastMaintenanceDate:yyyy-MM-dd}," +
$"{e.OperatingHours:F1},{e.Temperature:F1},{e.Pressure:F1},{e.Vibration:F2},{e.Remarks ?? ""}"));
await File.WriteAllLinesAsync(filePath, lines, System.Text.Encoding.UTF8);
}
#region 私有辅助方法
private string GetZoneCode(FactoryZone zone) => zone switch
{
FactoryZone.ProductionLineA => "PLA",
FactoryZone.ProductionLineB => "PLB",
FactoryZone.ProductionLineC => "PLC",
FactoryZone.Warehouse => "WH",
FactoryZone.QualityControl => "QC",
FactoryZone.Maintenance => "MNT",
_ => "UNK"
};
private string GetTypeCode(EquipmentType type) => type switch
{
EquipmentType.Motor => "MOT",
EquipmentType.Pump => "PMP",
EquipmentType.Valve => "VLV",
EquipmentType.Sensor => "SNR",
EquipmentType.Controller => "CTR",
EquipmentType.Conveyor => "CNV",
_ => "UNK"
};
private string GetTypeName(EquipmentType type) => type switch
{
EquipmentType.Motor => "电机",
EquipmentType.Pump => "泵",
EquipmentType.Valve => "阀门",
EquipmentType.Sensor => "传感器",
EquipmentType.Controller => "控制器",
EquipmentType.Conveyor => "输送带",
_ => "未知"
};
private string GetStatusName(EquipmentStatus status) => status switch
{
EquipmentStatus.Running => "运行中",
EquipmentStatus.Stopped => "停止",
EquipmentStatus.Maintenance => "维护中",
EquipmentStatus.Fault => "故障",
_ => "未知"
};
private string GetZoneName(FactoryZone zone) => zone switch
{
FactoryZone.ProductionLineA => "生产线A",
FactoryZone.ProductionLineB => "生产线B",
FactoryZone.ProductionLineC => "生产线C",
FactoryZone.Warehouse => "仓库",
FactoryZone.QualityControl => "质检区",
FactoryZone.Maintenance => "维护区",
_ => "未知"
};
private double GenerateRealisticTemperature(EquipmentStatus status)
{
return status switch
{
EquipmentStatus.Running => _random.NextDouble() * 30 + 40,
EquipmentStatus.Fault => _random.NextDouble() * 50 + 70,
EquipmentStatus.Maintenance => _random.NextDouble() * 10 + 20,
EquipmentStatus.Stopped => _random.NextDouble() * 10 + 20,
_ => _random.NextDouble() * 20 + 30
};
}
private double GenerateRealisticPressure(EquipmentType type)
{
return type switch
{
EquipmentType.Pump => _random.NextDouble() * 15 + 5,
EquipmentType.Valve => _random.NextDouble() * 10 + 3,
EquipmentType.Motor => _random.NextDouble() * 2 + 1,
EquipmentType.Controller => _random.NextDouble() * 1 + 0.5,
_ => _random.NextDouble() * 8 + 2
};
}
private double GenerateRealisticVibration(EquipmentStatus status)
{
return status switch
{
EquipmentStatus.Running => _random.NextDouble() * 2 + 0.5,
EquipmentStatus.Fault => _random.NextDouble() * 10 + 5,
EquipmentStatus.Maintenance => _random.NextDouble() * 0.5,
EquipmentStatus.Stopped => _random.NextDouble() * 0.2,
_ => _random.NextDouble() * 3 + 1
};
}
private string GenerateRandomRemark()
{
var remarks = new[]
{
"运行正常,性能良好",
"需要定期润滑保养",
"轴承噪声略高,建议检查",
"温度稍高,已加强冷却",
"振动值在正常范围内",
"最近更换了密封件",
"电流消耗正常",
"待下次维护时更换滤芯",
"压力传感器校准完成",
"控制程序已更新"
};
return remarks[_random.Next(remarks.Length)];
}
#endregion
}
}
C#using System.ComponentModel;
using System.Linq;
using AppMasterMemoryTest.Models;
using AppMasterMemoryTest.Services;
namespace AppMasterMemoryTest
{
public partial class FrmMain : Form
{
private EquipmentService? _equipmentService;
private DataPersistenceService _dataPersistenceService;
private MemoryDatabase? _database;
private BindingList<Equipment> _displayData;
public FrmMain()
{
InitializeComponent();
_dataPersistenceService = new DataPersistenceService();
_displayData = new BindingList<Equipment>();
InitializeControls();
UpdateStatusBar();
}
private void InitializeControls()
{
InitializeFilterControls();
dgvEquipment.DataSource = _displayData;
SetupDataGridViewColumns();
if (_dataPersistenceService.DatabaseExists())
{
tslStatus.Text = "发现现有数据库文件,请选择加载数据";
}
else
{
tslStatus.Text = "未找到数据库文件,请生成测试数据或加载数据";
}
}
private void InitializeFilterControls()
{
cmbType.Items.Add("全部");
cmbType.Items.AddRange(Enum.GetNames<EquipmentType>().Select(name => GetTypeName(Enum.Parse<EquipmentType>(name))).ToArray());
cmbType.SelectedIndex = 0;
cmbStatus.Items.Add("全部");
cmbStatus.Items.AddRange(Enum.GetNames<EquipmentStatus>().Select(name => GetStatusName(Enum.Parse<EquipmentStatus>(name))).ToArray());
cmbStatus.SelectedIndex = 0;
cmbZone.Items.Add("全部");
cmbZone.Items.AddRange(Enum.GetNames<FactoryZone>().Select(name => GetZoneName(Enum.Parse<FactoryZone>(name))).ToArray());
cmbZone.SelectedIndex = 0;
}
private void SetupDataGridViewColumns()
{
dgvEquipment.AutoGenerateColumns = false;
dgvEquipment.Columns.Clear();
// 创建绑定列
var colEquipmentId = new DataGridViewTextBoxColumn();
colEquipmentId.Name = "EquipmentId";
colEquipmentId.HeaderText = "设备ID";
colEquipmentId.DataPropertyName = "EquipmentId";
colEquipmentId.Width = 80;
colEquipmentId.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
dgvEquipment.Columns.Add(colEquipmentId);
var colEquipmentCode = new DataGridViewTextBoxColumn();
colEquipmentCode.Name = "EquipmentCode";
colEquipmentCode.HeaderText = "设备编号";
colEquipmentCode.DataPropertyName = "EquipmentCode";
colEquipmentCode.Width = 120;
dgvEquipment.Columns.Add(colEquipmentCode);
var colName = new DataGridViewTextBoxColumn();
colName.Name = "Name";
colName.HeaderText = "设备名称";
colName.DataPropertyName = "Name";
colName.Width = 120;
dgvEquipment.Columns.Add(colName);
var colType = new DataGridViewTextBoxColumn();
colType.Name = "Type";
colType.HeaderText = "设备类型";
colType.DataPropertyName = "Type";
colType.Width = 80;
dgvEquipment.Columns.Add(colType);
var colStatus = new DataGridViewTextBoxColumn();
colStatus.Name = "Status";
colStatus.HeaderText = "设备状态";
colStatus.DataPropertyName = "Status";
colStatus.Width = 80;
dgvEquipment.Columns.Add(colStatus);
var colZone = new DataGridViewTextBoxColumn();
colZone.Name = "Zone";
colZone.HeaderText = "工厂区域";
colZone.DataPropertyName = "Zone";
colZone.Width = 100;
dgvEquipment.Columns.Add(colZone);
var colPowerLevel = new DataGridViewTextBoxColumn();
colPowerLevel.Name = "PowerLevel";
colPowerLevel.HeaderText = "功率等级(kW)";
colPowerLevel.DataPropertyName = "PowerLevel";
colPowerLevel.Width = 90;
colPowerLevel.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
dgvEquipment.Columns.Add(colPowerLevel);
var colManufacturer = new DataGridViewTextBoxColumn();
colManufacturer.Name = "Manufacturer";
colManufacturer.HeaderText = "制造商";
colManufacturer.DataPropertyName = "Manufacturer";
colManufacturer.Width = 100;
dgvEquipment.Columns.Add(colManufacturer);
var colModel = new DataGridViewTextBoxColumn();
colModel.Name = "Model";
colModel.HeaderText = "型号";
colModel.DataPropertyName = "Model";
colModel.Width = 120;
dgvEquipment.Columns.Add(colModel);
var colTemperature = new DataGridViewTextBoxColumn();
colTemperature.Name = "Temperature";
colTemperature.HeaderText = "温度(°C)";
colTemperature.DataPropertyName = "Temperature";
colTemperature.Width = 80;
colTemperature.DefaultCellStyle.Format = "F1";
colTemperature.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
dgvEquipment.Columns.Add(colTemperature);
var colPressure = new DataGridViewTextBoxColumn();
colPressure.Name = "Pressure";
colPressure.HeaderText = "压力(bar)";
colPressure.DataPropertyName = "Pressure";
colPressure.Width = 80;
colPressure.DefaultCellStyle.Format = "F1";
colPressure.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
dgvEquipment.Columns.Add(colPressure);
var colVibration = new DataGridViewTextBoxColumn();
colVibration.Name = "Vibration";
colVibration.HeaderText = "振动(mm/s)";
colVibration.DataPropertyName = "Vibration";
colVibration.Width = 80;
colVibration.DefaultCellStyle.Format = "F2";
colVibration.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
dgvEquipment.Columns.Add(colVibration);
var colOperatingHours = new DataGridViewTextBoxColumn();
colOperatingHours.Name = "OperatingHours";
colOperatingHours.HeaderText = "运行小时数";
colOperatingHours.DataPropertyName = "OperatingHours";
colOperatingHours.Width = 100;
colOperatingHours.DefaultCellStyle.Format = "F1";
colOperatingHours.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
dgvEquipment.Columns.Add(colOperatingHours);
}
private void RefreshData()
{
if (_equipmentService == null) return;
try
{
var filteredData = ApplyFilters();
// 为了性能考虑,限制显示的记录数量
var displayData = filteredData.Take(10000).Select(equipment => new
{
equipment.EquipmentId,
equipment.EquipmentCode,
equipment.Name,
Type = GetTypeName(equipment.Type),
Status = GetStatusName(equipment.Status),
Zone = GetZoneName(equipment.Zone),
equipment.PowerLevel,
equipment.Manufacturer,
equipment.Model,
equipment.Temperature,
equipment.Pressure,
equipment.Vibration,
equipment.OperatingHours
}).ToList();
// 设置数据源
dgvEquipment.DataSource = displayData;
UpdateStatusBar();
var totalFiltered = filteredData.Count();
var displayed = displayData.Count;
if (totalFiltered > 10000)
{
tslStatus.Text = $"数据刷新完成,筛选出 {totalFiltered:N0} 条记录,显示前 {displayed:N0} 条";
}
else
{
tslStatus.Text = $"数据刷新完成,显示 {displayed:N0} 条记录";
}
}
catch (Exception ex)
{
MessageBox.Show($"刷新数据时发生错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
tslStatus.Text = "数据刷新失败";
}
}
private IEnumerable<Equipment> ApplyFilters()
{
if (_equipmentService == null) return Enumerable.Empty<Equipment>();
// 获取筛选条件
var keyword = txtSearch.Text.Trim();
var selectedType = cmbType.SelectedIndex > 0 ? (EquipmentType?)Enum.GetValues<EquipmentType>()[cmbType.SelectedIndex - 1] : null;
var selectedStatus = cmbStatus.SelectedIndex > 0 ? (EquipmentStatus?)Enum.GetValues<EquipmentStatus>()[cmbStatus.SelectedIndex - 1] : null;
var selectedZone = cmbZone.SelectedIndex > 0 ? (FactoryZone?)Enum.GetValues<FactoryZone>()[cmbZone.SelectedIndex - 1] : null;
var manufacturer = txtManufacturer.Text.Trim();
var minPower = nudMinPower.Value > 0 ? (int)nudMinPower.Value : (int?)null;
var maxPower = nudMaxPower.Value < 1000 ? (int)nudMaxPower.Value : (int?)null;
// 应用筛选
var result = _equipmentService.FilterEquipment(
type: selectedType,
status: selectedStatus,
zone: selectedZone,
manufacturer: string.IsNullOrEmpty(manufacturer) ? null : manufacturer,
minPowerLevel: minPower,
maxPowerLevel: maxPower
);
// 关键词搜索
if (!string.IsNullOrEmpty(keyword))
{
result = _equipmentService.SearchEquipment(keyword)
.Intersect(result, new EquipmentComparer());
}
return result.OrderBy(e => e.EquipmentId);
}
private void UpdateStatusBar()
{
if (_equipmentService != null)
{
var totalCount = _equipmentService.GetAllEquipment().Count();
tslRecordCount.Text = $"记录数: {totalCount:N0}";
}
else
{
tslRecordCount.Text = "记录数: 0";
}
var dbSize = _dataPersistenceService.GetDatabaseSize();
tslDatabaseSize.Text = $"数据库大小: {dbSize:F2} MB";
}
private void RefreshStatistics()
{
if (_equipmentService == null)
{
rtbStatistics.Text = "暂无数据";
return;
}
try
{
var stats = _equipmentService.GetStatistics();
var typeStats = _equipmentService.GetTypeStatistics().ToList();
var zoneStats = _equipmentService.GetZoneStatistics().ToList();
var text = $@"
═══════════════════════════════════════════════════════════════════
设备统计信息总览
═══════════════════════════════════════════════════════════════════
📊 总体统计
───────────────────────────────────────────────────────────────────
总设备数量: {stats.TotalEquipment:N0} 台
运行中设备: {stats.RunningEquipment:N0} 台 ({(double)stats.RunningEquipment / stats.TotalEquipment * 100:F1}%)
停止设备: {stats.StoppedEquipment:N0} 台 ({(double)stats.StoppedEquipment / stats.TotalEquipment * 100:F1}%)
维护中设备: {stats.MaintenanceEquipment:N0} 台 ({(double)stats.MaintenanceEquipment / stats.TotalEquipment * 100:F1}%)
故障设备: {stats.FaultEquipment:N0} 台 ({(double)stats.FaultEquipment / stats.TotalEquipment * 100:F1}%)
⚡ 运行参数统计
───────────────────────────────────────────────────────────────────
平均运行小时数: {stats.AverageOperatingHours:F1} 小时
平均温度: {stats.AverageTemperature:F1} °C
平均压力: {stats.AveragePressure:F1} bar
平均振动值: {stats.AverageVibration:F2} mm/s
🏆 极值设备
───────────────────────────────────────────────────────────────────
最高运行小时数: {stats.HighestOperatingHoursEquipment?.Name} ({stats.HighestOperatingHoursEquipment?.OperatingHours:F1} 小时)
最高温度设备: {stats.HighestTemperatureEquipment?.Name} ({stats.HighestTemperatureEquipment?.Temperature:F1} °C)
🔧 设备类型分布
───────────────────────────────────────────────────────────────────
";
foreach (var typeStat in typeStats)
{
text += $"{GetTypeName(typeStat.Type),-10}: {typeStat.Count,6:N0} 台 运行: {typeStat.RunningCount,6:N0} 台 故障率: {typeStat.FaultRate,5:F1}%\n";
}
text += @"
🏭 工厂区域分布
───────────────────────────────────────────────────────────────────
";
foreach (var zoneStat in zoneStats)
{
text += $"{GetZoneName(zoneStat.Zone),-12}: {zoneStat.EquipmentCount,4:N0} 台 平均温度: {zoneStat.AverageTemperature,5:F1}°C 故障数: {zoneStat.FaultCount,3} 台\n";
}
text += @"
───────────────────────────────────────────────────────────────────
报告生成时间: " + DateTime.Now.ToString("yyyy年MM月dd日 HH:mm:ss");
rtbStatistics.Text = text;
// 设置颜色
rtbStatistics.SelectAll();
rtbStatistics.SelectionColor = Color.FromArgb(64, 64, 64);
rtbStatistics.SelectionStart = 0;
rtbStatistics.SelectionLength = 0;
}
catch (Exception ex)
{
rtbStatistics.Text = $"生成统计信息时发生错误: {ex.Message}";
}
}
#region 事件处理
private async void btnGenerate_Click(object sender, EventArgs e)
{
var result = MessageBox.Show(
"将生成30万条测试数据,这可能需要几分钟时间。是否继续?",
"确认生成数据",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (result != DialogResult.Yes) return;
try
{
this.Enabled = false;
tslStatus.Text = "正在生成测试数据,请稍候...";
_database = await _dataPersistenceService.GenerateTestDataAsync(300000);
_equipmentService = new EquipmentService(_database);
tslStatus.Text = "测试数据生成完成";
RefreshData();
RefreshStatistics();
MessageBox.Show("30万条测试数据生成完成!", "完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"生成测试数据失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
tslStatus.Text = "生成测试数据失败";
}
finally
{
this.Enabled = true;
}
}
private async void btnLoad_Click(object sender, EventArgs e)
{
try
{
this.Enabled = false;
tslStatus.Text = "正在加载数据,请稍候...";
_database = await _dataPersistenceService.LoadDatabaseAsync();
_equipmentService = new EquipmentService(_database);
tslStatus.Text = "数据加载完成";
RefreshData();
RefreshStatistics();
MessageBox.Show("数据加载完成!", "完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"加载数据失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
tslStatus.Text = "加载数据失败";
}
finally
{
this.Enabled = true;
}
}
private async void btnSave_Click(object sender, EventArgs e)
{
if (_database == null)
{
MessageBox.Show("当前没有数据可保存", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
try
{
this.Enabled = false;
tslStatus.Text = "正在保存数据,请稍候...";
await _dataPersistenceService.SaveDatabaseAsync(_database);
tslStatus.Text = "数据保存完成";
UpdateStatusBar();
MessageBox.Show("数据保存完成!", "完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"保存数据失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
tslStatus.Text = "保存数据失败";
}
finally
{
this.Enabled = true;
}
}
private async void btnExport_Click(object sender, EventArgs e)
{
if (_database == null)
{
MessageBox.Show("当前没有数据可导出", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
using (var saveDialog = new SaveFileDialog())
{
saveDialog.Filter = "CSV文件|*.csv";
saveDialog.Title = "导出设备数据";
saveDialog.FileName = $"设备数据_{DateTime.Now:yyyyMMdd_HHmmss}.csv";
if (saveDialog.ShowDialog() == DialogResult.OK)
{
try
{
this.Enabled = false;
tslStatus.Text = "正在导出数据,请稍候...";
await _dataPersistenceService.ExportToCsvAsync(_database, saveDialog.FileName);
tslStatus.Text = "数据导出完成";
MessageBox.Show($"数据已导出到: {saveDialog.FileName}", "完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"导出数据失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
tslStatus.Text = "导出数据失败";
}
finally
{
this.Enabled = true;
}
}
}
}
private void btnRefresh_Click(object sender, EventArgs e)
{
RefreshData();
RefreshStatistics();
tslStatus.Text = "数据已刷新";
}
private void btnStatistics_Click(object sender, EventArgs e)
{
tabMain.SelectedTab = tpStatistics;
RefreshStatistics();
}
private void btnClearFilter_Click(object sender, EventArgs e)
{
txtSearch.Clear();
txtManufacturer.Clear();
cmbType.SelectedIndex = 0;
cmbStatus.SelectedIndex = 0;
cmbZone.SelectedIndex = 0;
nudMinPower.Value = 0;
nudMaxPower.Value = 1000;
RefreshData();
}
private void txtSearch_TextChanged(object sender, EventArgs e)
{
RefreshData();
}
private void Filter_Changed(object sender, EventArgs e)
{
RefreshData();
}
#endregion
#region 辅助方法
private string GetTypeName(EquipmentType type) => type switch
{
EquipmentType.Motor => "电机",
EquipmentType.Pump => "泵",
EquipmentType.Valve => "阀门",
EquipmentType.Sensor => "传感器",
EquipmentType.Controller => "控制器",
EquipmentType.Conveyor => "输送带",
_ => "未知"
};
private string GetStatusName(EquipmentStatus status) => status switch
{
EquipmentStatus.Running => "运行中",
EquipmentStatus.Stopped => "停止",
EquipmentStatus.Maintenance => "维护中",
EquipmentStatus.Fault => "故障",
_ => "未知"
};
private string GetZoneName(FactoryZone zone) => zone switch
{
FactoryZone.ProductionLineA => "生产线A",
FactoryZone.ProductionLineB => "生产线B",
FactoryZone.ProductionLineC => "生产线C",
FactoryZone.Warehouse => "仓库",
FactoryZone.QualityControl => "质检区",
FactoryZone.Maintenance => "维护区",
_ => "未知"
};
private class EquipmentComparer : IEqualityComparer<Equipment>
{
public bool Equals(Equipment? x, Equipment? y)
{
return x?.EquipmentId == y?.EquipmentId;
}
public int GetHashCode(Equipment obj)
{
return obj.EquipmentId.GetHashCode();
}
}
#endregion
}
}



C#// ✅ 推荐:使用复合索引
[SecondaryKey(0, keyOrder: 0), NonUnique]
public FactoryZone Zone { get; init; }
[SecondaryKey(0, keyOrder: 1), NonUnique]
public int PowerLevel { get; init; }
// ❌ 避免:过多的单独索引
// 会增加内存占用和构建时间
| 查询场景 | 传统数据库 | MasterMemory | 性能提升 |
|---|---|---|---|
| 简单筛选 | 50-200ms | <1ms | 200倍 |
| 复杂联合查询 | 200-800ms | 1-2ms | 400倍 |
| 范围查询 | 100-500ms | <1ms | 500倍 |
C#public class GenericQueryService<T> where T : class
{
private readonly MemoryDatabase _database;
public GenericQueryService(MemoryDatabase database)
{
_database = database;
}
// 🚀 高性能筛选模板
public IEnumerable<TResult> Query<TResult>(
Func<T, bool> predicate,
Func<T, TResult> selector,
int maxResults = 10000)
{
return GetAllData()
.Where(predicate)
.Take(maxResults)
.Select(selector);
}
protected virtual IEnumerable<T> GetAllData()
{
// 子类实现具体的数据获取逻辑
throw new NotImplementedException();
}
}
记住这句话:在内存为王的时代,谁掌握了高效的内存数据库技术,谁就掌握了性能优化的核心竞争力!
觉得这篇文章对你有帮助吗? 请点个赞👍并转发给更多需要性能优化的同行们!让我们一起在C#技术路上精进不止!
💡 想要完整源码? 关注公众号回复"MasterMemory源码"即可获取30万数据的完整demo项目!
本文为原创技术分享,如需转载请注明出处。更多C#进阶技巧,请关注本公众号!
相关信息
通过网盘分享的文件:AppMasterMemoryTest.zip 链接: https://pan.baidu.com/s/1OkLoCYG5EpMUAROZ5N7B6g?pwd=savx 提取码: savx --来自百度网盘超级会员v9的分享
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!