How to log OPC Unified Architecture data changes into a SQL Server database

From OPC Labs Knowledge Base
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

See also: QuickOPC.NET: How to log OPC Data Access item changes into an SQL database.

It is often required that a status of certain process variable is logged into a SQL database. Following example shows how to do that with QuickOPC:

        static void Main()
        {
            const string connectionString =
                "Data Source=(local);Initial Catalog=QuickOPCExamples;Integrated Security=true";

            Console.WriteLine("Starting up...");
            using (var connection = new SqlConnection(connectionString))
            {
                connection.Open();

                // Create all necessary ADO.NET objects.
                var adapter = new SqlDataAdapter("SELECT * FROM UASimpleLog", connection);
                var dataSet = new DataSet();
                adapter.FillSchema(dataSet, SchemaType.Source, "UASimpleLog");
                adapter.InsertCommand = new SqlCommandBuilder(adapter).GetInsertCommand();
                DataTable table = dataSet.Tables["UASimpleLog"];
                Debug.Assert(table != null);

                Console.WriteLine("Logging for 30 seconds...");
                // Subscribe to an OPC item, using an anonymous method to process the notifications.
                int handle = EasyUAClient.SharedInstance.SubscribeDataChange(
                    "http://opcua.demo-this.com:51211/UA/SampleServer",   // or "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
                    "nsu=http://test.org/UA/Data/;i=10853",
                    100,
                    (_, eventArgs) =>
                    {
                        Debug.Assert(eventArgs != null);
                        Console.Write(".");

                        // In this example, we only log valid data. Production logger would also log errors.
                        if (eventArgs.AttributeData != null)
                        {
                            // Fill a DataRow with the OPC data, and add it to a DataTable.
                            Debug.Assert(table.Rows != null);
                            table.Rows.Clear();
                            DataRow row = table.NewRow();
                            row["NodeID"] = eventArgs.Arguments.NodeDescriptor.NodeId;
                            row["Value"] = eventArgs.AttributeData.Value;
                            row["SourceTimestamp"] = (eventArgs.AttributeData.SourceTimestamp < (DateTime)SqlDateTime.MinValue)
                                                   ? (DateTime)SqlDateTime.MinValue
                                                   : eventArgs.AttributeData.SourceTimestamp;
                            row["ServerTimestamp"] = (eventArgs.AttributeData.ServerTimestamp < (DateTime)SqlDateTime.MinValue)
                                                   ? (DateTime)SqlDateTime.MinValue
                                                   : eventArgs.AttributeData.ServerTimestamp;
                            row["StatusCode"] = eventArgs.AttributeData.StatusCode.InternalValue;

                            Debug.Assert(table.Rows != null);
                            table.Rows.Add(row);

                            // Update the underlying DataSet using an insert command.
                            adapter.Update(dataSet, "UASimpleLog");
                        }
                    }
                    );
                Thread.Sleep(30 * 1000);
                Console.WriteLine();

                Console.WriteLine("Shutting down...");
                EasyUAClient.SharedInstance.UnsubscribeMonitoredItem(handle);
            }

            Console.WriteLine("Finished.");
        }

The database creation script is here:

CREATE DATABASE QuickOPCExamples;
GO

USE QuickOPCExamples;
GO

-- The "UASimpleLog" table stores values of all data types in a single SQL_VARIANT column, for OPC Unified Architecture.
CREATE TABLE UASimpleLog(
	NodeID nvarchar(100) NULL,
	Value sql_variant NULL,
	SourceTimestamp datetime NULL,
	ServerTimestamp datetime NULL,
	StatusCode int NULL
);
GO

And (part of) the resulting data may look like this:

Howtologopcunifiedarchitecturedatachangesintoansqldatabase.png

This example is included with the product (starting with version 5.41). Please use the example from the product itself for the most up-to-date code of the example.