Write a table plugin handler
- Last UpdatedApr 08, 2026
- 3 minute read
This scenario guides you through the steps required to write a plugin handler that the system can invoke for record changes in a particular table. For data export targets that require custom, table-specific message processing, you can write a table-specific plugin to override the behavior of the default handler.
To identify the code associated with each step, see the code comments in the Example code section.
To write the table-specific plugin handler
In this example, the handler code for the analog table is written to a file called AnalogHandler.cs.
- In the created project used to implement the plugin handler code for the table, open or create the class file.
- Set the class to implement the IRecordHandler interface.
- Create the IsInterestedIn() method where the system writes the logic that determines which records should be considered for export:
- Use the old and new versions of the record to determine whether the changes are of interest to the handler.
- Return true if the handler is interested in the record; otherwise, return false.
- Create the ExportRecord() method where the system writes the record processing logic:
- Use the old and new versions of the record to perform any custom processing.
- Export the record to its destination.
Example code
using System;
using OASySDNA.Common.Logging;
using OASySDNA.RealTime.Data.Common.HighPerformanceSetDBWrapper.Interfaces;
using OASySDNA.RealTime.HighPerformanceSetDB;
namespace OASySDNA.RealTime.DataExport.ExamplePlugin
{
/// <summary>
/// Example of a simple plugin that will be called when any analog record changes.
/// Detailed information on how to get the HPDEV sample plugin working can be found
/// in User documentation.
/// </summary>
public sealed class AnalogHandler : IRecordHandler
{
public String Name { get; } = "Analog Record Handler";
public String TableName { get; }
public readonly Int32 RecordNumberThreshold = 500000;
private IDNALog DNALog { get; }
public AnalogHandler(String tableName) : this(tableName, DNALogAdapter.Instance) { }
internal AnalogHandler(String tableName, IDNALog dnaLog)
{
TableName = tableName;
DNALog = dnaLog;
}
/// <summary>
/// Do custom processing when an analog record changes.
/// If curval is updated the old and new value will be written to the oasysErrLog.log
/// </summary>
/// <param name="message">The DataExport message for the record.</param>
public void ExportRecord(DataExportMessage message)
{
var recordNumber = message.RecordNumber;
var newRecord = message.NewRecord;
var oldRecord = message.OldRecord;
DNALog.Debug(quot;ExportRecord method invoked.");
var oldValue = oldRecord.ReadData<Double>("curval");
var newValue = newRecord.ReadData<Double>("curval");
DNALog.Debug(quot;AnalogHandler export point record number {recordNumber} old vs new curval: {oldValue} vs {newValue}");
if (oldRecord == newRecord)
{
DNALog.Verbose(quot;Old and New records are identical.");
}
else if (oldValue != newValue)
{
DNALog.Always(quot;Field curval changed, DO EXPORT CODE HERE. Old value is {oldValue} and new value is {newValue}");
}
else
{
DNALog.Verbose(quot;Field curval identical between old and new records. Old value is {oldValue} and new value is {newValue}");
}
}
/// <summary>
/// Decides if this record number from a RealTime database (RTDB) table should be considered for export.
/// This decision is made at the earliest spot in the upstream process to avoid
/// un-interesting records being passed through different stages.
/// </summary>
/// <param name="message">The DataExport message for the record.</param>
/// <returns> True if interested, thus allowing the record to be passed to this handler.</returns>
public Boolean IsInterestedIn(DataExportMessage message)
{
// Change this condition to (analog) slot numbers that data export is interested in.
if( message.RecordNumber < RecordNumberThreshold )
{
//using HPDBRealTimeBaseRecord is much faster, which is a important for IsInterestedIn
var oldValue = message.OldRecord.HPDBRealTimeBaseRecord.ReadDouble("curval");
var newValue = message.NewRecord.HPDBRealTimeBaseRecord.ReadDouble("curval");
//We're only interested if the value changed
return oldValue != newValue;
}
return false;
}
}
}