MySQL · RetrieveMultiple
Retrieve many records with a query
Many records with a query, in three scenarios: a condition and an order; several conditions together; and how many rows came back. Every value in a condition is sent as a parameter, never written into the SQL.
Set up for this page
Besides the sample itself, it uses SampleContext.cs (the dbContext every sample is given); SampleOutput.cs (Step and Show, which print), in the files below.
Before scenario 1 the sample runs this, so the service and the rows the scenarios use are there:
var service = new ArxMySqlDbService(connectionString, ArxSchemaCatalog.Create()
.Table("account", ArxIdColumn.Generated<long>("id"))
.Build());
var accounts = new List<ArxEntity>();
foreach (var (number, name, employees) in new[] { ("ACC-R201", "Basic Bikes", 12), ("ACC-R202", "Basic Boats", 340), ("ACC-R203", "Basic Books", 45) })
{
var account = new ArxEntity("account");
account["name"] = name;
account["account_number"] = number;
account["employee_count"] = employees;
accounts.Add(account);
}
await service.CreateMultipleAsync(accounts);1 A condition and an order
The accounts whose name begins with "Basic B", by name.
Already in scope: service (ArxMySqlDbService)
var query = new ArxQueryExpression("account");
query.ColumnSet.AddColumns("name", "employee_count");
query.Criteria.AddCondition("name", ArxConditionOperator.BeginsWith, "Basic B");
query.AddOrder("name", ArxOrderType.Ascending);
ArxEntityCollection result = await service.RetrieveMultipleAsync(query);
Console.WriteLine($"{string.Join(", ", result.Entities.Select(x => x["name"]))}");Check it in the database
Run it in any SQL tool connected to the database, after the code has run.
SELECT name
FROM account
WHERE name LIKE 'Basic B%'
ORDER BY name;Expect: 3 rows, Basic Bikes, Basic Boats, Basic Books.
2 Several conditions
Conditions in the criteria are joined with AND: "Basic" accounts with 40 employees or more.
Already in scope: service (ArxMySqlDbService)
var query = new ArxQueryExpression("account");
query.ColumnSet.AddColumns("name", "employee_count");
query.Criteria.AddCondition("name", ArxConditionOperator.BeginsWith, "Basic B");
query.Criteria.AddCondition("employee_count", ArxConditionOperator.GreaterEqual, 40);
query.AddOrder("employee_count", ArxOrderType.Descending);
var result = await service.RetrieveMultipleAsync(query);
Console.WriteLine($"{string.Join(", ", result.Entities.Select(x => $"{x["name"]} ({x["employee_count"]})"))}");Check it in the database
Run it in any SQL tool connected to the database, after the code has run.
SELECT name, employee_count
FROM account
WHERE name LIKE 'Basic B%' AND employee_count >= 40
ORDER BY employee_count DESC;Expect: 2 rows, Basic Boats 340, Basic Books 45.
3 How many came back
Without paging, TotalRecordCount is the number of rows that came back.
Already in scope: service (ArxMySqlDbService)
var query = new ArxQueryExpression("account");
query.ColumnSet.AddColumn("name");
query.Criteria.AddCondition("account_number", ArxConditionOperator.In, "ACC-R201", "ACC-R203", "ACC-R999");
var result = await service.RetrieveMultipleAsync(query);
Console.WriteLine($"{result.TotalRecordCount} of the 3 numbers asked for");Check it in the database
Run it in any SQL tool connected to the database, after the code has run.
SELECT count(*)
FROM account
WHERE account_number IN ('ACC-R201', 'ACC-R203', 'ACC-R999');Expect: 2 (nobody has ACC-R999).
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.MySQL --version 1.0.0-rc.1 - Database: a MySQL 8.4 (tested with 8.4.13) database with the sample schema.
- Configuration: set
ARX_SAMPLES_MYSQLto its connection string. Nothing is hard-coded. - Source code: replace
Program.csand add the 3 other files 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.MySQL;
using ArxSamples.MySQL.Operations.RetrieveMultiple.Basics;
// The connection string comes from the environment, never from the code (see "Configure the connection").
var connectionString = Environment.GetEnvironmentVariable("ARX_SAMPLES_MYSQL")
?? throw new InvalidOperationException("Set the ARX_SAMPLES_MYSQL environment variable to your MySQL connection string.");
await new Basic1_RetrieveManyRecords().RunAsync(new SampleContext(connectionString));
The sample, as it is in the repository.
using ARX.SDK.MySQL.Services;
using ARX.SDK.Query;
using ARX.SDK.Services;
using static ArxSamples.MySQL.SampleOutput;
namespace ArxSamples.MySQL.Operations.RetrieveMultiple.Basics;
/// <summary>
/// Many records with a query, in three scenarios: a condition and an order; several conditions together; and how many
/// rows came back. Every value in a condition is sent as a parameter, never written into the SQL.
/// </summary>
public sealed class Basic1_RetrieveManyRecords : ISample
{
public string Name => "retrieve-multiple-basics-1-retrieve-many-records";
public string Title => "Retrieve many records with a query";
public async Task RunAsync(SampleContext dbContext)
{
var service = new ArxMySqlDbService(dbContext.ConnectionString, ArxSchemaCatalog.Create()
.Table("account", ArxIdColumn.Generated<long>("id"))
.Build());
var accounts = new List<ArxEntity>();
foreach (var (number, name, employees) in new[] { ("ACC-R201", "Basic Bikes", 12), ("ACC-R202", "Basic Boats", 340), ("ACC-R203", "Basic Books", 45) })
{
var account = new ArxEntity("account");
account["name"] = name;
account["account_number"] = number;
account["employee_count"] = employees;
accounts.Add(account);
}
await service.CreateMultipleAsync(accounts);
await Scenario1_AConditionAndAnOrderAsync(service);
await Scenario2_SeveralConditionsAsync(service);
await Scenario3_HowManyCameBackAsync(service);
}
/// <summary>1. The accounts whose name begins with "Basic B", by name.</summary>
private static async Task Scenario1_AConditionAndAnOrderAsync(ArxMySqlDbService service)
{
Step("1. A condition and an order");
var query = new ArxQueryExpression("account");
query.ColumnSet.AddColumns("name", "employee_count");
query.Criteria.AddCondition("name", ArxConditionOperator.BeginsWith, "Basic B");
query.AddOrder("name", ArxOrderType.Ascending);
ArxEntityCollection result = await service.RetrieveMultipleAsync(query);
Show($"{string.Join(", ", result.Entities.Select(x => x["name"]))}");
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT name
* FROM account
* WHERE name LIKE 'Basic B%'
* ORDER BY name;
* -- Expect: 3 rows, Basic Bikes, Basic Boats, Basic Books.
* ===========================================================
*/
}
/// <summary>2. Conditions in the criteria are joined with AND: "Basic" accounts with 40 employees or more.</summary>
private static async Task Scenario2_SeveralConditionsAsync(ArxMySqlDbService service)
{
Step("2. Several conditions");
var query = new ArxQueryExpression("account");
query.ColumnSet.AddColumns("name", "employee_count");
query.Criteria.AddCondition("name", ArxConditionOperator.BeginsWith, "Basic B");
query.Criteria.AddCondition("employee_count", ArxConditionOperator.GreaterEqual, 40);
query.AddOrder("employee_count", ArxOrderType.Descending);
var result = await service.RetrieveMultipleAsync(query);
Show($"{string.Join(", ", result.Entities.Select(x => $"{x["name"]} ({x["employee_count"]})"))}");
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT name, employee_count
* FROM account
* WHERE name LIKE 'Basic B%' AND employee_count >= 40
* ORDER BY employee_count DESC;
* -- Expect: 2 rows, Basic Boats 340, Basic Books 45.
* ===========================================================
*/
}
/// <summary>3. Without paging, TotalRecordCount is the number of rows that came back.</summary>
private static async Task Scenario3_HowManyCameBackAsync(ArxMySqlDbService service)
{
Step("3. How many came back");
var query = new ArxQueryExpression("account");
query.ColumnSet.AddColumn("name");
query.Criteria.AddCondition("account_number", ArxConditionOperator.In, "ACC-R201", "ACC-R203", "ACC-R999");
var result = await service.RetrieveMultipleAsync(query);
Show($"{result.TotalRecordCount} of the 3 numbers asked for");
/* ===========================================================
* [DIRECT QUERY CHECK]
* -----------------------------------------------------------
* SELECT count(*)
* FROM account
* WHERE account_number IN ('ACC-R201', 'ACC-R203', 'ACC-R999');
* -- Expect: 2 (nobody has ACC-R999).
* ===========================================================
*/
}
}
What every sample is given: the connection string (and the ISample interface the samples implement).
namespace ArxSamples.MySQL;
/// <summary>One documentation sample: a scenario a real application has, shown end to end.</summary>
public interface ISample
{
/// <summary>The name to run it alone: <c>dotnet run -- <name></c>.</summary>
string Name { get; }
/// <summary>One line on what it shows.</summary>
string Title { get; }
Task RunAsync(SampleContext dbContext);
}
/// <summary>
/// What a sample is given. Every sample gets the connection string; the application's service and catalog
/// (SampleContext.Application.cs) and the plain MySqlConnector read-back helper (SampleContext.Direct.cs) live in their own
/// files, so a sample needs only the files it uses.
/// </summary>
public sealed partial class SampleContext
{
public SampleContext(string connectionString)
{
ConnectionString = connectionString;
}
public string ConnectionString { get; }
}
How the samples print: Step for each scenario, Show for what it did, ShowError for an error caught on purpose.
using ARX.SDK;
namespace ArxSamples.MySQL;
/// <summary>How the samples print: a numbered step for each scenario, then what it did.</summary>
public static class SampleOutput
{
/// <summary>The start of a scenario: <c>Step("1. By the id Create returned")</c>.</summary>
public static void Step(string text) => Console.WriteLine($" > {text}");
/// <summary>What the scenario did.</summary>
public static void Show(string text) => Console.WriteLine($" {text}");
/// <summary>An ARX error the scenario caught on purpose.</summary>
public static void ShowError(ArxException exception)
=> Console.WriteLine($" caught {exception.GetType().Name}: {exception.Message}");
}
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. A condition and an order
Basic Bikes, Basic Boats, Basic Books
> 2. Several conditions
Basic Boats (340), Basic Books (45)
> 3. How many came back
2 of the 3 numbers asked for