要使用C#从KepServerEX读取数据并存入MySQL,主要有两种主流方法,你可以根据项目需求选择。下表对比了这两种方案的核心区别:
| 特性/需求 | 方案一:使用KepServerEX内置DataLogger | 方案二:编写C# OPC客户端程序 |
|---|---|---|
| 核心原理 | 配置KepServerEX,利用其DataLogger 功能将数据自动写入MySQL-1-8。 | 使用C#编写独立程序,通过OPC DA/UA库 主动读取数据,再写入MySQL-5-7。 |
| 开发量 | 极小,主要为配置工作,无需编码。 | 大,需开发完整的C#客户端程序。 |
| 灵活性 | 低,依赖KepServerEX的日志组、触发器等配置。 | 高,可完全自定义数据逻辑、处理规则和存储方式。 |
| 实时性 | 依赖触发器 配置(如定时、值变化)-8,非强实时。 | 高,可灵活控制读取频率和时机。 |
| 推荐场景 | 数据记录规则简单、希望快速上手、无需二次开发。 | 需要复杂数据处理、与业务系统深度集成、或KepServerEX版本不支持DataLogger。 |
方案一:使用KepServerEX内置DataLogger(推荐快速实现)
如果你追求快速部署且数据记录规则简单,这通常是最直接的方法-1。主要步骤包括:
-
安装MySQL ODBC驱动 :从MySQL官网下载并安装对应系统位数的ODBC驱动(如
Connector/ODBC)-1-8。 -
配置系统ODBC数据源 :在Windows的ODBC数据源管理器中,添加一个指向你MySQL数据库的系统DSN-1。
-
在KepServerEX中配置DataLogger:
-
启动日志组:配置完成后启动,数据便会自动写入MySQL。
这个方案的完整配置示例,可以参考博客园上的教程《使用Kepserver自带DataLogger功能实现工控数据转储关系型数据库》-8。
方案二:编写C# OPC客户端程序(推荐灵活控制)
如果需要更灵活地处理数据,或与现有C#系统集成,可以编写独立的客户端程序。下图清晰地展示了该方案的完整数据流和工作流程:
图表
代码

MySQL数据库
C# 客户端程序
KepServerEX OPC服务器
"OPC DA/UA协议通信"
"执行INSERT语句"
"通道(Channel)"
"设备(Device)"
"标签(Tags)"
"初始化OPC连接
OPCDAAuto.dll / OPCFoundation SDK"
"读取/订阅标签值"
"处理数据"
"写入MySQL数据库
MySql.Data.MySqlClient"
"数据表 (如 tag_log)"
以下是实现此方案的关键步骤和代码示例。
1. 创建数据库表
首先,在MySQL中创建存储数据的表。
sq
CREATE TABLE `tag_log` (
`id` INT NOT NULL AUTO_INCREMENT,
`tag_name` VARCHAR(255) NOT NULL,
`tag_value` VARCHAR(255),
`quality` VARCHAR(50),
`timestamp` DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
INDEX `idx_tag_name` (`tag_name`),
INDEX `idx_timestamp` (`timestamp`)
);
2. 核心C#代码实现
创建一个C#控制台或Windows服务项目,通过NuGet安装 OpcNetApi (用于OPC DA) 或 OPCFoundation.NetStandard.Opc.Ua (用于OPC UA) 以及 MySql.Data 包。
下面是使用 OPC DA 协议读取数据并存入MySQL的简化示例:
csharp
using System;
using Opc;
using Opc.Da;
using MySql.Data.MySqlClient;
namespace KepServerToMySql
{
class Program
{
// 数据库连接字符串,需修改为你的信息
static string mySqlConnStr = "server=localhost;user id=youruser;password=yourpwd;database=yourdb;";
// KepServerEX的OPC DA服务器地址,需修改
static string opcServerUrl = "opcda://localhost/Kepware.KEPServerEX.V6";
static void Main(string[] args)
{
// 初始化OPC服务器连接
Opc.Da.Server server = ConnectToOpcServer(opcServerUrl);
if (server == null) return;
// 定义要读取的标签列表
Item[] itemsToRead = new Item[]
{
new Item { ItemName = "通道1.设备1.标签1" },
new Item { ItemName = "通道1.设备1.标签2" }
};
// 创建订阅并读取数据
Subscription subscription = CreateSubscription(server);
ItemValueResult[] values = ReadOpcTags(server, itemsToRead);
// 处理并存储读取到的数据
if (values != null)
{
ProcessAndStoreValues(values);
}
Console.WriteLine("按任意键退出...");
Console.ReadKey();
}
static Opc.Da.Server ConnectToOpcServer(string url)
{
try
{
Opc.URL opcUrl = new Opc.URL(url);
OpcCom.Factory factory = new OpcCom.Factory();
Opc.Da.Server server = new Opc.Da.Server(factory, null);
server.Connect(opcUrl, new Opc.ConnectData(new System.Net.NetworkCredential()));
Console.WriteLine($"成功连接到OPC服务器: {url}");
return server;
}
catch (Exception ex)
{
Console.WriteLine($"连接OPC服务器失败: {ex.Message}");
return null;
}
}
static Subscription CreateSubscription(Opc.Da.Server server)
{
SubscriptionState state = new SubscriptionState
{
Name = "DataLoggerSubscription",
Active = true,
UpdateRate = 1000 // 更新频率(毫秒)
};
return (Subscription)server.CreateSubscription(state);
}
static ItemValueResult[] ReadOpcTags(Opc.Da.Server server, Item[] items)
{
try
{
ItemValueResult[] results = server.Read(items);
Console.WriteLine($"成功读取 {results.Length} 个标签。");
return results;
}
catch (Exception ex)
{
Console.WriteLine($"读取标签失败: {ex.Message}");
return null;
}
}
static void ProcessAndStoreValues(ItemValueResult[] values)
{
using (MySqlConnection conn = new MySqlConnection(mySqlConnStr))
{
conn.Open();
foreach (var item in values)
{
// 构建插入SQL语句
string sql = @"INSERT INTO tag_log (tag_name, tag_value, quality)
VALUES (@tagName, @tagValue, @quality);";
using (MySqlCommand cmd = new MySqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("@tagName", item.ItemName);
cmd.Parameters.AddWithValue("@tagValue", item.Value?.ToString() ?? "NULL");
cmd.Parameters.AddWithValue("@quality", item.Quality.ToString());
try
{
int affectedRows = cmd.ExecuteNonQuery();
if (affectedRows > 0)
{
Console.WriteLine($"已存储标签 [{item.ItemName}] = {item.Value}");
}
}
catch (MySqlException dbEx)
{
Console.WriteLine($"数据库插入失败 ({item.ItemName}): {dbEx.Message}");
}
}
}
}
}
}
}
关键配置与优化建议
-
OPC连接与安全 :确保C#程序运行在可访问KepServerEX OPC服务的机器上,可能需要配置
DCOM设置(对于OPC DA)或证书(对于OPC UA)。 -
数据库优化 :对于高频数据,考虑批量插入而非逐条插入,并定期归档历史数据。
-
程序健壮性 :在生产环境中,将程序封装为Windows服务 ,并加入详细的日志记录 和异常恢复机制。
-
KepServerEX配置 :务必在KepServerEX中正确创建通道、设备和需要读取的数据标签 (Tags)-10。
总结
总的来说,如果你的目标是快速 实现一个稳定、无需开发的数据记录功能,方案一(DataLogger)是首选 -1-8。如果你的需求涉及复杂的数据处理逻辑 、与现有C#系统的深度集成 ,或者KepServerEX版本不支持 DataLogger,那么方案二(编写C#客户端) 提供了最大的灵活性和控制力。
你可以根据上述对比和自身情况做出选择。如果你能告诉我更多关于你的项目细节(例如数据点的数量、希望读取的频率、是否有特殊的数据处理需求等),我可以为你提供更具体的建议。