Read and call
In this tutorial, you add the client to a .NET application, read rows from a view, and call a procedure.
Prerequisites
- a console application targeting
net10.0with the packagesWkl.Data.Gateway.ClientandMicrosoft.Extensions.Hosting - a running data service and its address
- a data source in the service (
fachdatenin the example) with a viewcontainer_typ(columnsid,bezeichnung) and a procedurestamm.farbe_speichern; replace these names with your own - a key whose rule may read the view and execute the procedure
Steps
Provide the key. The key is set in an environment variable of the process, never in a file of the application:
$env:WKL_GATEWAY_API_KEY = '<key>'
Enter the address. In the application's
appsettings.json:{ "GatewayClient": { "BaseAddress": "https://daten.example.com/" } }All settings are listed under Configuration.
Register, read, call.
Program.cs:using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Wkl.Data.Gateway.Client; using Wkl.Data.Gateway.Contracts; var builder = Host.CreateApplicationBuilder(args); builder.Services.AddGatewayClient(builder.Configuration.GetSection(GatewayClientOptions.SectionName)); using var host = builder.Build(); // Starting the host validates the settings; a missing BaseAddress stops the application here await host.StartAsync(); var client = host.Services.GetRequiredService<IGatewayClient>(); // Read at most 100 rows whose description contains "DV", sorted by id, with the total count var page = await client.ReadAsync<ContainerTyp>(new GatewayQuery( new GatewayResource("fachdaten", GatewayResourceKind.View, "container_typ"), select: ["id", "bezeichnung"], filter: new GatewayFilter.Comparison("bezeichnung", GatewayComparisonOperator.Contains, "DV"), orderBy: [new GatewaySortField("id", GatewaySortDirection.Ascending)], top: 100, includeTotalCount: true)); foreach (var row in page.Rows) { Console.WriteLine($"{row.Id}: {row.Bezeichnung}"); } Console.WriteLine($"{page.Rows.Count} of {page.TotalCount} rows"); // Call the procedure with two arguments; null is sent as SQL NULL var result = await client.InvokeAsync<SpeicherErgebnis>(new GatewayRoutineRequest( new GatewayResource("fachdaten", GatewayResourceKind.Procedure, "stamm.farbe_speichern"), new Dictionary<string, object?> { ["ral_nummer"] = "RAL 5010", ["name_en"] = null })); Console.WriteLine(result.ReturnedRows && result.Rows.Count > 0 ? $"Saved as {result.Rows[0].Id}" : $"{result.AffectedRowCount} rows changed"); public sealed class ContainerTyp { public int Id { get; init; } public string Bezeichnung { get; init; } = string.Empty; } public sealed class SpeicherErgebnis { public int Id { get; init; } }
Column names in
snake_caseare mapped to ordinary property names:LastChangedUtcreadslast_changed_utc(compared case-insensitively). No attribute per property is needed for this; with a few hundred columns, it would mainly be a place to make typos. The mapping only covers columns that are themselves named insnake_case, though. A column such asChangedOnorA&Bneeds a property with[JsonPropertyName("…")]and exactly that name; without it, the property silently keeps its default value, with no error. Inselect,filter, andorderBy, name a column with characters other than letters, digits, and_in the service's encoded form, for exampleA_x0026_BforA&B(see API reference). If you need the rows unchanged, read intoJsonElement.
Result
The application prints the rows it read, followed by how many rows the filter matches in total
(page.TotalCount is only set because includeTotalCount is set). If the procedure returns a row,
the last line shows its id; otherwise, the number of rows changed.
Next steps
- Limits and properties—above all:
TotalCountcan be missing