通过 C# 中的 OPC UA 客户端使用 ADO.NET 实体数据模型插入数据库
Insert to Database with ADO.NET Entity Data Model through OPC UA Client in C#
我正在尝试使用 ADO.NET 实体数据模型和来自 OPCFoundation/UA-.NETStandard 的示例客户端写入数据库。我是 C# 的新手,我的问题是 lamda 表达式位于:
list.ForEach(i => i.Notification += OnNotification);
只要服务器上的值发生变化,客户端就会收到实际值(这称为订阅)。下面的函数显示了函数 OnNotification
.
private static void OnNotification(MonitoredItem item, MonitoredItemNotificationEventArgs e)
{
foreach (var value in item.DequeueValues())
{
Console.WriteLine("{0}: {1}, {2}, {3}", item.DisplayName, value.Value, value.SourceTimestamp, value.StatusCode);
}
}
函数的输出看起来像这样:
Column01: 4545, 11.12.2017 13:34, Good
Column02: 6767, 11.12.2017 13:34, Good
Column01: 4456, 11.12.2017 13:35, Good
Column02: 5554, 11.12.2017 13:35, Good
Column02: 6664, 11.12.2017 13:36, Good
Column01: 6233, 11.12.2017 13:37, Good
Column02: 5123, 11.12.2017 13:37, Good
更改值时会生成输出,并一直持续到您按下某个键为止。请注意,有时列不会出现,因为值保持不变。在这种情况下,该值可以作为 NULL 添加到数据库中。
为了将数据获取到数据库中,我想到了将 OnNotification
函数修改为如下内容:
private static void OnNotification(MonitoredItem item, MonitoredItemNotificationEventArgs e)
{
Entities context = new Entities();
dbName objData = new dbName();
objData.SourceTimestamp = System.DateTime.Now;
foreach (var value in item.DequeueValues())
{
switch (item.DisplayName)
{
case "Column01":
objData.Column01 = Convert.ToInt16(value.Value);
break;
case "Column02":
objData.Columns02 = Convert.ToInt16(value.Value);
break;
default:
Console.WriteLine("Unknown Displayname: {0}", item.DisplayName);
break;
}
}
context.dbName.Add(objData);
context.SaveChanges();
}
现在我可以将值插入 Column01 和 Column02,但只能插入不同的行。所以我的 Table 在数据库中看起来像这样:
SourceTimestamp | Column01 | Column02
11.12.2017 13:34 | 4545 | NULL
11.12.2017 13:34 | NULL | 6767
11.12.2017 13:35 | 4456 | NULL
11.12.2017 13:35 | NULL | 5554
11.12.2017 13:36 | NULL | 6664
11.12.2017 13:37 | 6233 | NULL
11.12.2017 13:37 | NULL | 5123
但我想要:
SourceTimestamp | Column01 | Column02
11.12.2017 13:34 | 4545 | 6767
11.12.2017 13:35 | 4456 | 5554
11.12.2017 13:36 | NULL | 6664
11.12.2017 13:37 | 6233 | 5123
问题是我无法控制的lambda表达式的循环,我不知道如何处理这个问题。我只需要获取一条订阅消息,将它们声明到列变量并将它们添加到数据库中,但这对我来说似乎有点棘手,而且由于我缺乏 C# 经验,我似乎无法解决问题。欢迎提出建议或其他解决方案。提前致谢。
Ii 似乎每个 'MonitoredItem' 在每个事件的队列中只有一个值。
这就是为什么你得到
Column01: 4545, 11.12.2017 13:34, Good
Column02: 6767, 11.12.2017 13:34, Good
Column01: 4456, 11.12.2017 13:35, Good
Column02: 5554, 11.12.2017 13:35, Good
Column02: 6664, 11.12.2017 13:36, Good
Column01: 6233, 11.12.2017 13:37, Good
Column02: 5123, 11.12.2017 13:37, Good
作为输出。 MonitoredItem 似乎具有唯一标识符:CientHandle。
因此,在您的事件处理程序中,您必须使用该标识符测试现有 dbName 对象的数据上下文,并更新该对象(如果存在)。如果不存在,则使用要更新的标识符创建一个新的 dbName 对象。
对于数据记录,我只是创建一个循环,读取值,将它们写入数据库,稍等片刻,重复。
那么所有的值都有相同的时间戳。
ps: 有些人可能会先使用 RegisterNodes,但这不是必需的!
pps: 这是一些代码。
```
Console.WriteLine("5a - Read values at an interval of 1 second, for 20 seconds.");
var readValueIds = new ReadValueId[]
{
new ReadValueId{ NodeId= NodeId.Parse("i=2258"), AttributeId = Attributes.Value }, // column 0
new ReadValueId{ NodeId= NodeId.Parse("i=2258"), AttributeId = Attributes.Value }, // column 1
};
var cts = new CancellationTokenSource(20000);
while (!cts.IsCancellationRequested)
{
var resp = session.Read(null, 0, TimestampsToReturn.Both, readValueIds, out DataValueCollection results, out DiagnosticInfoCollection infos);
Console.WriteLine($"ts:{results[0].SourceTimestamp}, c0: {results[0].Value}, c1: {results[1].Value}");
await Task.Delay(1000);
}
```
我正在尝试使用 ADO.NET 实体数据模型和来自 OPCFoundation/UA-.NETStandard 的示例客户端写入数据库。我是 C# 的新手,我的问题是 lamda 表达式位于:
list.ForEach(i => i.Notification += OnNotification);
只要服务器上的值发生变化,客户端就会收到实际值(这称为订阅)。下面的函数显示了函数 OnNotification
.
private static void OnNotification(MonitoredItem item, MonitoredItemNotificationEventArgs e)
{
foreach (var value in item.DequeueValues())
{
Console.WriteLine("{0}: {1}, {2}, {3}", item.DisplayName, value.Value, value.SourceTimestamp, value.StatusCode);
}
}
函数的输出看起来像这样:
Column01: 4545, 11.12.2017 13:34, Good
Column02: 6767, 11.12.2017 13:34, Good
Column01: 4456, 11.12.2017 13:35, Good
Column02: 5554, 11.12.2017 13:35, Good
Column02: 6664, 11.12.2017 13:36, Good
Column01: 6233, 11.12.2017 13:37, Good
Column02: 5123, 11.12.2017 13:37, Good
更改值时会生成输出,并一直持续到您按下某个键为止。请注意,有时列不会出现,因为值保持不变。在这种情况下,该值可以作为 NULL 添加到数据库中。
为了将数据获取到数据库中,我想到了将 OnNotification
函数修改为如下内容:
private static void OnNotification(MonitoredItem item, MonitoredItemNotificationEventArgs e)
{
Entities context = new Entities();
dbName objData = new dbName();
objData.SourceTimestamp = System.DateTime.Now;
foreach (var value in item.DequeueValues())
{
switch (item.DisplayName)
{
case "Column01":
objData.Column01 = Convert.ToInt16(value.Value);
break;
case "Column02":
objData.Columns02 = Convert.ToInt16(value.Value);
break;
default:
Console.WriteLine("Unknown Displayname: {0}", item.DisplayName);
break;
}
}
context.dbName.Add(objData);
context.SaveChanges();
}
现在我可以将值插入 Column01 和 Column02,但只能插入不同的行。所以我的 Table 在数据库中看起来像这样:
SourceTimestamp | Column01 | Column02
11.12.2017 13:34 | 4545 | NULL
11.12.2017 13:34 | NULL | 6767
11.12.2017 13:35 | 4456 | NULL
11.12.2017 13:35 | NULL | 5554
11.12.2017 13:36 | NULL | 6664
11.12.2017 13:37 | 6233 | NULL
11.12.2017 13:37 | NULL | 5123
但我想要:
SourceTimestamp | Column01 | Column02
11.12.2017 13:34 | 4545 | 6767
11.12.2017 13:35 | 4456 | 5554
11.12.2017 13:36 | NULL | 6664
11.12.2017 13:37 | 6233 | 5123
问题是我无法控制的lambda表达式的循环,我不知道如何处理这个问题。我只需要获取一条订阅消息,将它们声明到列变量并将它们添加到数据库中,但这对我来说似乎有点棘手,而且由于我缺乏 C# 经验,我似乎无法解决问题。欢迎提出建议或其他解决方案。提前致谢。
Ii 似乎每个 'MonitoredItem' 在每个事件的队列中只有一个值。 这就是为什么你得到
Column01: 4545, 11.12.2017 13:34, Good
Column02: 6767, 11.12.2017 13:34, Good
Column01: 4456, 11.12.2017 13:35, Good
Column02: 5554, 11.12.2017 13:35, Good
Column02: 6664, 11.12.2017 13:36, Good
Column01: 6233, 11.12.2017 13:37, Good
Column02: 5123, 11.12.2017 13:37, Good
作为输出。 MonitoredItem 似乎具有唯一标识符:CientHandle。
因此,在您的事件处理程序中,您必须使用该标识符测试现有 dbName 对象的数据上下文,并更新该对象(如果存在)。如果不存在,则使用要更新的标识符创建一个新的 dbName 对象。
对于数据记录,我只是创建一个循环,读取值,将它们写入数据库,稍等片刻,重复。
那么所有的值都有相同的时间戳。
ps: 有些人可能会先使用 RegisterNodes,但这不是必需的!
pps: 这是一些代码。
```
Console.WriteLine("5a - Read values at an interval of 1 second, for 20 seconds.");
var readValueIds = new ReadValueId[]
{
new ReadValueId{ NodeId= NodeId.Parse("i=2258"), AttributeId = Attributes.Value }, // column 0
new ReadValueId{ NodeId= NodeId.Parse("i=2258"), AttributeId = Attributes.Value }, // column 1
};
var cts = new CancellationTokenSource(20000);
while (!cts.IsCancellationRequested)
{
var resp = session.Read(null, 0, TimestampsToReturn.Both, readValueIds, out DataValueCollection results, out DiagnosticInfoCollection infos);
Console.WriteLine($"ts:{results[0].SourceTimestamp}, c0: {results[0].Value}, c1: {results[1].Value}");
await Task.Delay(1000);
}
```