簡體   English   中英

通過C#中的OPC UA客戶端插入具有ADO.NET實體數據模型的數據庫

[英]Insert to Database with ADO.NET Entity Data Model through OPC UA Client in C#

我正在嘗試使用來自OPCFoundation / UA-.NETStandard的示例客戶端使用ADO.NET實體數據模型寫入數據庫。 我是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#的經驗,我似乎無法解決問題。 歡迎提出建議或其他解決方案。 提前致謝。

我似乎每個“ 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);
        }

```

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM