Orpheus Table
Orpheus table is the core class of OrpheusORM. It is responsible for the actual executing of the
- Delete
- Update
- Insert
commands to modify data. It's also responsible for loading data, with or without criteria. So you can load all the data of the underlying database table or a subset of it.
It is model agnostic and you can declaratively define the model for the table. The model for the table is/should be basically a representation of the database table fields.
When to use it
There is no limitation per se, for when to use the OrpheusTable class. From a logical separation perspective, it would make more sense, if you were saving data to a table that has no detail tables. Orpheus Module is the class to use, when you have multiple tables, with dependencies to each other.
A quick example
Let's assume you have the following model
public enum TestModelTransactorType
{
ttCustomer,
ttSupplier
}
public class TestModelTransactor
{
[PrimaryKey]
public Guid TransactorId { get; set; }
[Length(30)]
public string Code { get; set; }
[Length(120)]
public string Description { get; set; }
[Length(120)]
public string Address { get; set; }
[Length(250)]
public string Email { get; set; }
public TestModelTransactorType Type { get; set; }
}
You can declare the table in your code
public class TransactorsTable:OrpheusTable<TestModelTransactor>
{
}
var transactorsTable = new TransactorsTable();
or create an instance of the table using the OrpheusDatabase (see DI Configuration
for how to get an IOrpheusDatabase instance)
var transactorsTable = db.CreateTable<TestModelTransactor>();
Note: The database does not keep a reference for the created table.
After you have a table instance, you can add, update and delete data from your table.
var transactorsTable = db.CreateTable<TestModelTransactor>();
var transactor = new TestModelTransactor(){
TransactorId = Guid.NewGuid(),
Code = '001',
Description = 'Transactor1'
};
transactorsTable.Add(transactor);
transactorsTable.Save();
Note:The table save will be executed within a transaction, so in case of any error, changes will be rolled back.
Async
Every I/O method on IOrpheusTable<T> has an async counterpart — LoadAsync/SaveAsync — backed
by real DbConnection/DbCommand/DbDataReader async I/O, not a synchronous call wrapped in
Task.Run. The sync methods remain fully supported; prefer the async ones for scalability in
server-side code.
await transactorsTable.LoadAsync();
transactorsTable.Add(transactor);
await transactorsTable.SaveAsync(cancellationToken);
LoadAsync has the same overloads as Load, including loading from a raw SQL string or an
IDbCommand:
await transactorsTable.LoadAsync("SELECT * FROM TestModelTransactor WHERE Type = 0");
Batching
When you Save() (or SaveAsync()) a table with many pending Add/Update/Delete operations,
Orpheus doesn't execute one round trip per row. Instead it chunks the pending rows into batches
and sends one multi-row command per batch:
- Inserts (for tables without a DB-generated key) use a multi-row
INSERT ... VALUES (...),(...),.... - Deletes use a single
WHERE key IN (...)/ OR-composite command. - Updates send multiple parameterized
UPDATEstatements in one batch (the same technique EF Core uses internally). - Tables with a DB-generated key are also batched, using an engine-specific technique to retrieve the generated keys for the whole batch in one round trip (see Orpheus DDL Helper).
The batch size defaults to 100 rows and can be changed per table:
transactorsTable.BatchSize = 250;