PostgreSQL · RetrieveMultiple
Read a view
A view, read like a table, in two scenarios: the view as it is (no declaration needed: no RecordId); and the view declared with its id, so its rows carry a RecordId and Retrieve by id works.
Set up for this page
The scenarios build on the sample application: SampleContext.cs (the dbContext every sample is given); SampleOutput.cs (Step and Show, which print); SampleContext.Application.cs (dbContext.Service, the application's ARX service); SampleCatalog.cs (the tables' ids, keys, lookups and display names).
Before scenario 1 the sample runs this, so the service and the rows the scenarios use are there:
var account = new ArxEntity("account");
account["name"] = "Viewed Ventures";
account["account_number"] = "ACC-R661";
var accountId = await service.CreateAsync(account);
foreach (var first in new[] { "Vera", "Vik" })
{
var contact = new ArxEntity("contact");
contact["first_name"] = first;
contact["last_name"] = "View-R661";
contact["account_id"] = new ArxEntityReference("account", accountId);
await service.CreateAsync(contact);
}1 The view as it is
vw_account_overview (an account and its number of contacts), filtered like a table.
Already in scope: service (ArxPgDbService)
var query = new ArxQueryExpression("vw_account_overview");
query.ColumnSet.AddColumns("name", "contacts");
query.Criteria.AddCondition("account_number", ArxConditionOperator.Equal, "ACC-R661");
var row = (await service.RetrieveMultipleAsync(query)).Entities[0];
Console.WriteLine($"{row["name"]}: {row["contacts"]} contacts, RecordId {(row.RecordId == null ? "none (the view isn't declared)" : row.RecordId)}");Check it in the database
Run it in any SQL tool connected to the database, after the code has run.
SELECT name, contacts
FROM vw_account_overview
WHERE account_number = 'ACC-R661';Expect: 1 row, Viewed Ventures, 2.
2 The view declared with its id
Declared with its id (a view has no primary key, so the id is supplied, not generated): RecordId and Retrieve by id.
Already in scope: connectionString (string), accountId (ArxRecordId)
var service = new ArxPgDbService(connectionString, ArxSchemaCatalog.Create()
.Table("vw_account_overview", ArxIdColumn.Supplied<long>("id"))
.Build());
var row = await service.RetrieveAsync("vw_account_overview", accountId.AsInt64(), new ArxColumnSet("name", "contacts")) ?? throw new InvalidOperationException("The vw_account_overview record isn't there.");
Console.WriteLine($"Retrieve by id: {row["name"]}, RecordId {row.RecordId}");Check it in the database
Run it in any SQL tool connected to the database, after the code has run.
SELECT o.name, o.contacts
FROM vw_account_overview o
JOIN account a ON a.id = o.id
WHERE a.account_number = 'ACC-R661';Expect: 1 row, Viewed Ventures, 2.
Run the complete sample
The code above comes from one program, built in a fresh project and run against the database. To run it yourself, here is every file and step.
The program, its files and how to run it
Run it locally
- .NET SDK: .NET SDK 10.0.100 or later 10.0.x (target
net10.0). - Create the project:
Terminal dotnet new console -n ArxSample -f net10.0 cd ArxSample - Install the packages:
Terminal dotnet add package ARX.SDK.PostgreSql --version 1.0.0-rc.1 - Database: a PostgreSQL 16 (tested with 16.15) database with the sample schema.
- Configuration: set
ARX_SAMPLES_POSTGRESQLto its connection string. Nothing is hard-coded. - Source code: add the files of the sample application this sample uses (
SampleContext.cs,SampleOutput.cs,SampleContext.Application.cs,SampleCatalog.cs), then replaceProgram.csand add the other file below, with the file names shown. - Run it:
Terminal dotnet run - Expected output: below.
The files
Runs the sample. Generated for this page; it reads the connection string from the environment.
using ArxSamples.PostgreSql;
using ArxSamples.PostgreSql.Operations.RetrieveMultiple.RealCases;
// The connection string comes from the environment, never from the code (see "Configure the connection").
var connectionString = Environment.GetEnvironmentVariable("ARX_SAMPLES_POSTGRESQL")
?? throw new InvalidOperationException("Set the ARX_SAMPLES_POSTGRESQL environment variable to your PostgreSQL connection string.");
await new RealCase5_ReadAView().RunAsync(new SampleContext(connectionString));
The sample, as it is in the repository.
using ARX.SDK.PostgreSql.Services;
using ARX.SDK.Query;
using ARX.SDK.Services;
using static ArxSamples.PostgreSql.SampleOutput;
namespace ArxSamples.PostgreSql.Operations.RetrieveMultiple.RealCases;
/// <summary>
/// A view, read like a table, in two scenarios: the view as it is (no declaration needed: no RecordId); and the view
/// declared with its id, so its rows carry a RecordId and Retrieve by id works.
/// </summary>
public sealed class RealCase5_ReadAView : ISample
{
public string Name => "retrieve-multiple-real-5-read-a-view";
public string Title => "Read a view";
public async Task RunAsync(SampleContext dbContext)
{
var account = new ArxEntity("account");
account["name"] = "Viewed Ventures";
account["account_number"] = "ACC-R661";
var accountId = await dbContext.Service.CreateAsync(account);
foreach (var first in new[] { "Vera", "Vik" })
{
var contact = new ArxEntity("contact");
contact["first_name"] = first;
contact["last_name"] = "View-R661";
contact["account_id"] = new ArxEntityReference("account", accountId);
await dbContext.Service.CreateAsync(contact);
}
await Scenario1_TheViewAsItIsAsync(dbContext);
await Scenario2_DeclaredWithItsIdAsync(dbContext, accountId);
}
/// <summary>1. vw_account_overview (an account and its number of contacts), filtered like a table.</summary>
private static async Task Scenario1_TheViewAsItIsAsync(SampleContext dbContext)
{
Step("1. The view as it is");
var query = new ArxQueryExpression("vw_account_overview");
query.ColumnSet.AddColumns("name", "contacts");
query.Criteria.AddCondition("account_number", ArxConditionOperator.Equal, "ACC-R661");
var row = (await dbContext.Service.RetrieveMultipleAsync(query)).Entities[0];
Show($"{row["name"]}: {row["contacts"]} contacts, RecordId {(row.RecordId == null ? "none (the view isn't declared)" : row.RecordId)}");
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT name, contacts
* FROM vw_account_overview
* WHERE account_number = 'ACC-R661';
* -- Expect: 1 row, Viewed Ventures, 2.
* ===========================================================
*/
}
/// <summary>2. Declared with its id (a view has no primary key, so the id is supplied, not generated): RecordId and Retrieve by id.</summary>
private static async Task Scenario2_DeclaredWithItsIdAsync(SampleContext dbContext, ArxRecordId accountId)
{
Step("2. The view declared with its id");
var service = new ArxPgDbService(dbContext.ConnectionString, ArxSchemaCatalog.Create()
.Table("vw_account_overview", ArxIdColumn.Supplied<long>("id"))
.Build());
var row = await service.RetrieveAsync("vw_account_overview", accountId.AsInt64(), new ArxColumnSet("name", "contacts")) ?? throw new InvalidOperationException("The vw_account_overview record isn't there.");
Show($"Retrieve by id: {row["name"]}, RecordId {row.RecordId}");
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT o.name, o.contacts
* FROM vw_account_overview o
* JOIN account a ON a.id = o.id
* WHERE a.account_number = 'ACC-R661';
* -- Expect: 1 row, Viewed Ventures, 2.
* ===========================================================
*/
}
}
Expected output
What dotnet run printed when the sample was verified, on a freshly created sample schema. Ids differ when the tables already hold rows.
> 1. The view as it is
Viewed Ventures: 2 contacts, RecordId none (the view isn't declared)
> 2. The view declared with its id
Retrieve by id: Viewed Ventures, RecordId 1