DataApiClient - Unified Client
- Last UpdatedJul 30, 2026
- 6 minute read
- Engineering
- Integration Service 4.1
- Integrators
Namespace: AVEVA.IntegrationService.DataAPI.SDK
Interface: IDataApiClient
Description
DataApiClient is a unified client that simplifies working with datasources without needing to know the specific product category. It provides a single interface to communicate with any type of datasource (Engineering, Excel, SQL, Simulation, ETAP, ERM, etc.) without creating category-specific clients.
This client is ideal when you want to work with multiple datasource types in a generic way or when you don't know the datasource type at design time.
Creating DataApiClient
using AVEVA.IntegrationService.DataAPI.SDK;
string host = "https://your-server/integration/v1";
string token = "your-access-token";
// Create unified DataApiClient
var dataApiClient = new DataApiClient(
host: host,
authType: AuthenticationType.Connect,
waitingTimeInMinutesForLiveData: 60,
connectToken: token,
hubCancellationToken: null
);
// Register token refresh handler
dataApiClient.RegisterTokenRefreshHandler(async () =>
{
// Your token refresh logic
return await RefreshTokenAsync();
});
Methods
GetDataSources
Retrieves all available datasources grouped by product category.
Signature:
Task<DataSet> GetDataSources(string accessToken = null)
Example:
// Create unified client
var dataApiClient = new DataApiClient(
host: "https://your-server/integration/v1",
authType: AuthenticationType.Connect,
waitingTimeInMinutesForLiveData: 60,
connectToken: "your-token"
);
// Get all datasources
DataSet allDataSources = await dataApiClient.GetDataSources();
// Each table in the DataSet represents a product category
foreach (DataTable categoryTable in allDataSources.Tables)
{
Console.WriteLine($"Category: {categoryTable.TableName}");
Console.WriteLine($"Datasources: {categoryTable.Rows.Count}");
foreach (DataRow row in categoryTable.Rows)
{
Console.WriteLine($" - {row["Name"]}");
}
}
GetMetaData
Retrieves metadata information for a specific datasource.
Signature:
Task<IEnumerable<KeyValuePair<string, string>>> GetMetaData(string datasourceName, string accessToken = null)
Example:
var metadata = await dataApiClient.GetMetaData("MyDataSource");
foreach (var item in metadata)
{
Console.WriteLine($"{item.Key}: {item.Value}");
}
GetTables
Retrieves list of tables under a datasource.
Signature:
Task<DataTable> GetTables(string datasourceName, string accessToken = null)
Example:
DataTable tables = await dataApiClient.GetTables("MyDataSource");
foreach (DataRow row in tables.Rows)
{
Console.WriteLine($"Table: {row["TableName"]}");
}
GetTableData
Retrieves data from a specific table with optional filtering.
Signature:
Task<DataTable> GetTableData(
string datasourceName,
string tableName,
string filterExp = "",
string accessToken = null
)
Example:
// Get all data from a table
DataTable data = await dataApiClient.GetTableData(
datasourceName: "MyDataSource",
tableName: "Equipment"
);
Console.WriteLine($"Retrieved {data.Rows.Count} rows");
// Get filtered data
DataTable filteredData = await dataApiClient.GetTableData(
datasourceName: "MyDataSource",
tableName: "Equipment",
filterExp: "Status eq 'Active' and Cost gt 10000"
);
Console.WriteLine($"Filtered to {filteredData.Rows.Count} active equipment items");
GetTableSchema
Retrieves schema information for a specific table.
Signature:
Task<DataTable> GetTableSchema(string datasourceName, string tableName, string accessToken = null)
Example:
DataTable schema = await dataApiClient.GetTableSchema("MyDataSource", "Equipment");
foreach (DataColumn column in schema.Columns)
{
Console.WriteLine($"Column: {column.ColumnName}, Type: {column.DataType}");
}
GetAcknowledgements
Retrieves all acknowledgements for a datasource.
Signature:
Task<IEnumerable<Acknowledgement>> GetAcknowledgements(string datasourceName, string accessToken = null)
Example:
var acknowledgements = await dataApiClient.GetAcknowledgements("MyDataSource");
foreach (var ack in acknowledgements)
{
Console.WriteLine($"AckId: {ack.Id}, Created: {ack.CreatedDate}, Status: {ack.Status}");
}
GetTableDataByAcknowledgementId
Retrieves data associated with a specific acknowledgement ID.
Signature:
Task<DataTable> GetTableDataByAcknowledgementId(
string datasourceName,
string acknowledgementId,
string accessToken = null
)
Example:
DataTable ackData = await dataApiClient.GetTableDataByAcknowledgementId(
"MyDataSource",
"ack-12345-67890"
);
Console.WriteLine($"Retrieved {ackData.Rows.Count} rows from acknowledgement");
GetDatasetByAcknowledgementId
Retrieves complete dataset (all tables) for an acknowledgement, handling chunking automatically.
Signature:
Task<DataSet> GetDatasetByAcknowledgementId(
string datasourceName,
string acknowledgementId,
string accessToken = null
)
Example:
DataSet dataset = await dataApiClient.GetDatasetByAcknowledgementId(
"MyDataSource",
"ack-12345-67890"
);
foreach (DataTable table in dataset.Tables)
{
Console.WriteLine($"Table: {table.TableName}, Rows: {table.Rows.Count}");
}
GetAcknowledgementMetaData
Retrieves metadata about an acknowledgement (chunk information, etc.).
Signature:
Task<AckMetaData> GetAcknowledgementMetaData(
string dataSourceName,
string acknowledgementId,
string accessToken = null
)
Example:
var metadata = await dataApiClient.GetAcknowledgementMetaData(
"MyDataSource",
"ack-12345-67890"
);
Console.WriteLine($"Total Chunks: {metadata.TotalChunks}");
Console.WriteLine($"Current Chunk: {metadata.CurrentChunk}");
Console.WriteLine($"Has More Data: {metadata.HasMore}");
GetAcknowledgementDataWithChunkId
Retrieves data for a specific chunk within an acknowledgement.
Signature:
Task<DataTable> GetAcknowledgementDataWithChunkId(
string datasourceName,
string acknowledgementId,
int chunkId,
string accessToken = null
)
Example:
// Get specific chunk
DataTable chunkData = await dataApiClient.GetAcknowledgementDataWithChunkId(
"MyDataSource",
"ack-12345-67890",
chunkId: 2
);
Console.WriteLine($"Chunk 2 contains {chunkData.Rows.Count} rows");
PostTables
Posts table list information to a datasource.
Signature:
Task<AcknowledgementResult> PostTables(
string datasourceName,
List<Table> tables,
string AckId,
string Context = "",
string Topic = "",
string accessToken = null,
int expiryDuration = 0
)
Example:
var tables = new List<Table>
{
new Table { Name = "Equipment", Description = "Equipment master data" },
new Table { Name = "Locations", Description = "Plant locations" }
};
var result = await dataApiClient.PostTables(
datasourceName: "MyDataSource",
tables: tables,
AckId: "",
Context: "{\"Operation\":\"TableListUpdate\"}",
Topic: "TableUpdates",
expiryDuration: 24
);
Console.WriteLine($"Posted tables. AckId: {result.AcknowledgementId}");
PostTableSchema
Posts schema definition for a table.
Signature:
Task<AcknowledgementResult> PostTableSchema(
string datasourceName,
string datatableName,
DataTable dataTable,
string AckId,
string Context = "",
string Topic = "",
string accessToken = null,
int expiryDuration = 0
)
Example:
// Create schema definition
DataTable schemaTable = new DataTable("Equipment");
schemaTable.Columns.Add("EquipmentID", typeof(string));
schemaTable.Columns.Add("Name", typeof(string));
schemaTable.Columns.Add("Status", typeof(string));
schemaTable.Columns.Add("Cost", typeof(decimal));
var result = await dataApiClient.PostTableSchema(
datasourceName: "MyDataSource",
datatableName: "Equipment",
dataTable: schemaTable,
AckId: "",
Context: "{\"SchemaVersion\":\"2.0\"}",
expiryDuration: 48
);
Console.WriteLine($"Posted schema. AckId: {result.AcknowledgementId}");
PostTableData
Posts data to a specific table.
Signature:
Task<AcknowledgementResult> PostTableData(
string datasourceName,
string datatableName,
DataTable dataTable,
string AckId,
string Context = "",
string Topic = "",
string accessToken = null,
int expiryDuration = 0
)
Example:
// Create data to post
DataTable equipmentData = new DataTable("Equipment");
equipmentData.Columns.Add("EquipmentID", typeof(string));
equipmentData.Columns.Add("Name", typeof(string));
equipmentData.Columns.Add("Status", typeof(string));
equipmentData.Columns.Add("Cost", typeof(decimal));
equipmentData.Rows.Add("EQ001", "Pump A", "Active", 15000.00);
equipmentData.Rows.Add("EQ002", "Tank B", "Active", 25000.00);
equipmentData.Rows.Add("EQ003", "Valve C", "Maintenance", 5000.00);
var result = await dataApiClient.PostTableData(
datasourceName: "MyDataSource",
datatableName: "Equipment",
dataTable: equipmentData,
AckId: "",
Context: "{\"Operation\":\"BulkInsert\",\"Source\":\"Migration\"}",
Topic: "EquipmentUpdates",
expiryDuration: 72
);
Console.WriteLine($"Posted {equipmentData.Rows.Count} equipment records");
Console.WriteLine($"AckId: {result.AcknowledgementId}");
PostMemo
Posts a memo (notification without data payload).
Signature:
Task<string> PostMemo(
string datasourceName,
Acknowledgement memo,
string accessToken = null,
int expiryDuration = 0
)
Example:
var memo = new Acknowledgement
{
Context = "{\"Type\":\"Notification\",\"Message\":\"Data refresh completed\",\"Severity\":\"Info\"}",
Topic = "SystemNotifications"
};
string ackId = await dataApiClient.PostMemo(
datasourceName: "MyDataSource",
memo: memo,
expiryDuration: 24
);
Console.WriteLine($"Posted memo. AckId: {ackId}");
PostData
Generic post method that can handle DataTable, DataSet, or string data.
Signature:
Task<AcknowledgementResult> PostData(
string datasourceName,
object data,
string ackId,
string requestPath,
string context = "",
string topic = "",
string accessToken = null,
int expiryDuration = 0
)
Example:
// Post DataTable
DataTable data = new DataTable("CustomData");
data.Columns.Add("Field1", typeof(string));
data.Columns.Add("Field2", typeof(int));
data.Rows.Add("Value1", 100);
var result = await dataApiClient.PostData(
datasourceName: "MyDataSource",
data: data,
ackId: "",
requestPath: "/CustomData",
context: "{\"DataType\":\"Custom\"}",
topic: "CustomDataTopic",
expiryDuration: 24
);
// Post DataSet
DataSet dataset = new DataSet();
dataset.Tables.Add(data);
var result2 = await dataApiClient.PostData(
datasourceName: "MyDataSource",
data: dataset,
ackId: "",
requestPath: "/CustomDataSet",
expiryDuration: 48
);
// Post JSON string
string jsonData = "{\"key\":\"value\",\"number\":123}";
var result3 = await dataApiClient.PostData(
datasourceName: "MyDataSource",
data: jsonData,
ackId: "",
requestPath: "/CustomJson",
expiryDuration: 12
);
Console.WriteLine($"Posted data. AckId: {result.AcknowledgementId}");
DeleteAcknowledgements
Deletes multiple acknowledgements in bulk.
Signature:
Task<DeleteAckResult> DeleteAcknowledgements(
string dataSourceName,
List<string> acks,
string accessToken = null
)
Example:
var ackIds = new List<string>
{
"ack-12345-67890",
"ack-12345-67891",
"ack-12345-67892"
};
var result = await dataApiClient.DeleteAcknowledgements(
dataSourceName: "MyDataSource",
acks: ackIds
);
Console.WriteLine($"Deleted {result.DeletedCount} acknowledgements");
Console.WriteLine($"Failed: {result.FailedCount}");
Console.WriteLine($"Status: {result.StatusCode}");
RegisterTokenRefreshHandler
Registers a handler for automatic token refresh.
Signature:
void RegisterTokenRefreshHandler(Func<Task<string>> handler)
Example:
dataApiClient.RegisterTokenRefreshHandler(async () =>
{
Console.WriteLine("Token refresh requested...");
// Call your identity service to get a new token
string newToken = await GetNewAccessTokenAsync();
return newToken;
});
Complete DataApiClient Example
using AVEVA.IntegrationService.DataAPI.SDK;
using System;
using System.Data;
using System.Threading.Tasks;
public class UnifiedDataApiExample
{
private DataApiClient _client;
public async Task InitializeAsync()
{
string host = "https://your-server/integration/v1";
string token = "your-access-token";
// Create unified client
_client = new DataApiClient(
host: host,
authType: AuthenticationType.Connect,
waitingTimeInMinutesForLiveData: 60,
connectToken: token
);
// Register token refresh
_client.RegisterTokenRefreshHandler(RefreshTokenAsync);
Console.WriteLine("DataApiClient initialized");
}
public async Task WorkWithMultipleDatasourcesAsync()
{
// Get all datasources across all categories
DataSet allDatasources = await _client.GetDataSources();
Console.WriteLine($"Found {allDatasources.Tables.Count} product categories");
// Work with any datasource without knowing its type
foreach (DataTable category in allDatasources.Tables)
{
Console.WriteLine($"\nCategory: {category.TableName}");
foreach (DataRow ds in category.Rows)
{
string dsName = ds["Name"].ToString();
Console.WriteLine($" Datasource: {dsName}");
// Get tables for this datasource
var tables = await _client.GetTables(dsName);
Console.WriteLine($" Tables: {tables.Rows.Count}");
// Get data from first table
if (tables.Rows.Count > 0)
{
string tableName = tables.Rows[0]["TableName"].ToString();
var data = await _client.GetTableData(dsName, tableName);
Console.WriteLine($" {tableName} has {data.Rows.Count} rows");
}
}
}
}
public async Task PostAndRetrieveDataAsync()
{
// Create data
DataTable newData = new DataTable("MyTable");
newData.Columns.Add("ID", typeof(int));
newData.Columns.Add("Name", typeof(string));
newData.Columns.Add("Value", typeof(decimal));
for (int i = 1; i <= 100; i++)
{
newData.Rows.Add(i, $"Item {i}", i * 10.5m);
}
// Post data
var result = await _client.PostTableData(
datasourceName: "MyDataSource",
datatableName: "MyTable",
dataTable: newData,
AckId: "",
Context: "{\"Operation\":\"Import\"}",
expiryDuration: 48
);
Console.WriteLine($"Posted data. AckId: {result.AcknowledgementId}");
// Retrieve the posted data
var retrievedData = await _client.GetTableDataByAcknowledgementId(
"MyDataSource",
result.AcknowledgementId
);
Console.WriteLine($"Retrieved {retrievedData.Rows.Count} rows");
// Get complete dataset with all chunks
var dataset = await _client.GetDatasetByAcknowledgementId(
"MyDataSource",
result.AcknowledgementId
);
Console.WriteLine($"Dataset contains {dataset.Tables.Count} tables");
}
public async Task ManageAcknowledgementsAsync()
{
string datasourceName = "MyDataSource";
// Get all acknowledgements
var acks = await _client.GetAcknowledgements(datasourceName);
Console.WriteLine($"Found {acks.Count()} acknowledgements");
// Find old acknowledgements to delete
var oldAcks = acks
.Where(a => a.CreatedDate < DateTime.Now.AddDays(-7))
.Select(a => a.Id)
.ToList();
if (oldAcks.Any())
{
// Delete old acknowledgements
var deleteResult = await _client.DeleteAcknowledgements(
datasourceName,
oldAcks
);
Console.WriteLine($"Deleted {deleteResult.DeletedCount} old acknowledgements");
}
}
private async Task<string> RefreshTokenAsync()
{
// Your token refresh logic
Console.WriteLine("Refreshing access token...");
return await GetNewTokenFromIdentityProvider();
}
private async Task<string> GetNewTokenFromIdentityProvider()
{
// Implementation of token refresh
await Task.Delay(100); // Simulate API call
return "new-refreshed-token";
}
}
// Usage
var example = new UnifiedDataApiExample();
await example.InitializeAsync();
await example.WorkWithMultipleDatasourcesAsync();
await example.PostAndRetrieveDataAsync();
await example.ManageAcknowledgementsAsync();
When to Use DataApiClient
Use DataApiClient when:
-
You need to work with multiple datasource types dynamically
-
You do not know the datasource product category at design time
-
You want a simpler, unified API across all datasource types
-
You are building a generic tool that works with any datasource
-
You need datasource discovery capabilities
Use specific clients (EngineeringClient, ExcelClient, etc.) when:
-
You know the exact datasource type at design time
-
You need product-specific methods not available in DataApiClient
-
You want strongly-typed results for specific product categories
-
You are working primarily with one datasource type