Table of Contents


Database Class Methods Reference


Summary

This section provides a comprehensive reference of all Database class methods organized by operation type. All methods are static and can be called directly using the Database class.

Query Methods

Query methods retrieve entity records using LINQ expressions. All query methods return SqlExpressionVisitor<T> which supports method chaining and lazy evaluation.

Method SignatureReturn TypeDescription
Query<T>()SqlExpressionVisitor<T>Starts a query for all records of entity T
Query<T>(Expression<Func<T, bool>> func)SqlExpressionVisitor<T>Starts a query with LINQ expression filter
QueryAll<T>()SqlExpressionVisitor<T>Query all records including soft-deleted items
QueryAll<T>(Expression<Func<T, bool>> func)SqlExpressionVisitor<T>Query including deleted records with LINQ filter

Query Extension Methods

Extension methods provide additional query functionality including execution, filtering, sorting, pagination, and eager loading.

Method SignatureReturn TypeDescription
ToList()List<T>Executes the query and returns results as a list
ToListAsAdmin()List<T>Executes the query with system privileges (bypasses user permissions)
First()TReturns the first record matching the query criteria
FirstAsAdmin()TReturns the first record with system privileges
Count()longReturns the count of records matching the query criteria
CountAsAdmin()longReturns the count with system privileges
Where(Expression<Func<T, bool>> predicate)SqlExpressionVisitor<T>Filters records based on LINQ expression
OrderBy(Expression<Func<T, object>> selector)SqlExpressionVisitor<T>Sorts records in ascending order by specified field
OrderByDescending(Expression<Func<T, object>> selector)SqlExpressionVisitor<T>Sorts records in descending order by specified field
ThenBy(Expression<Func<T, object>> selector)SqlExpressionVisitor<T>Applies secondary ascending sort
ThenByDescending(Expression<Func<T, object>> selector)SqlExpressionVisitor<T>Applies secondary descending sort
Limit(int take)SqlExpressionVisitor<T>Limits the number of records returned
Limit(int take, int skip)SqlExpressionVisitor<T>Limits records returned and skips specified number (for pagination)
Include(Expression<Func<T, object>> relationship)SqlExpressionVisitor<T>Eager loads related entity (loads Id and Name fields only)
Include(Expression<Func<T, object>> relationship, Expression<Func<TRelated, object>> fields)SqlExpressionVisitor<T>Eager loads related entity with specific fields specified
IncludeAll(Fields mode)SqlExpressionVisitor<T>Controls which fields to load: Fields.All or Fields.IdAndName
ToListAsync()Task<List<T>>Async equivalent of ToList(). Awaits results without blocking the request thread.
ToListAsAdminAsync()Task<List<T>>Async equivalent of ToListAsAdmin(). Runs with system privileges.
FirstAsync()Task<T>Async equivalent of First(). Returns null if no record matches.
FirstAsAdminAsync()Task<T>Async equivalent of FirstAsAdmin(). Returns null if no record matches.
CountAsync()Task<long>Async equivalent of Count().
CountAsAdminAsync()Task<long>Async equivalent of CountAsAdmin().
ToQueryResultAsync()Task<QueryResult<T>>Async pageable result with records, total count, and pagination metadata.

Count Methods

Count methods return the number of records matching specified criteria without retrieving the actual records.

Method SignatureReturn TypeDescription
Count<T>(Expression<Func<T, bool>> func)longCounts records matching the LINQ expression filter

Search Methods

Search methods perform full-text search across searchable entity fields with additional filtering capabilities.

Method SignatureReturn TypeDescription
Search(string searchQuery, params object[] parameters)IEnumerable<dbObject>Dynamic search using FIND syntax: FIND {keywords} IN {area}.{entityname} [WHERE conditions] ORDER BY {expr} {direction} SELECT a,b,c [LIMIT take,skip]
Search<T>(string keywords)SqlExpressionVisitor<T>Full-text search across all searchable fields
Search<T>(string keywords, IEnumerable<string> searchFields)SqlExpressionVisitor<T>Full-text search on specific fields only
Search<T>(string keywords, string conditions, IEnumerable<object> parameters, IEnumerable<string> selectFields, IEnumerable<string> searchFields)SqlExpressionVisitor<T>Full-text search with additional filters, field selection, and specific search fields

Retrieve Methods

Retrieve methods fetch a single record by its unique identifier.

Method SignatureReturn TypeDescription
Retrieve(string id)dbObjectRetrieves a single record by ID (determines entity type from ID)
Retrieve(string id, DatabaseOptions dbOptions)dbObjectRetrieves a single record by ID with database options
Retrieve<T>(string id)TRetrieves a single record by ID (generic, strongly-typed)
Retrieve<T>(string id, DatabaseOptions dbOptions)TRetrieves a single record by ID with database options (generic)
Database.RetrieveAsync<T>(string id)Task<T>Async equivalent of Retrieve<T>(id). Returns null if no record found.

Create Methods

Create methods insert new records into the database.

Method SignatureReturn TypeDescription
Create(dbObject model, DatabaseOptions dbOptions = null)SaveResultInserts a single record
Create<T>(IEnumerable<T> models, DatabaseOptions dbOptions = null)IEnumerable<SaveResult>Inserts multiple records in a single bulk operation
Database.CreateAsync(dbObject record)Task<SaveResult>Async single-record insert.
Database.CreateAsync(IEnumerable<dbObject> records)Task<IEnumerable<SaveResult>>Async bulk insert.

Edit Methods

Edit methods update existing records in the database.

Method SignatureReturn TypeDescription
Edit(dbObject model, DatabaseOptions dbOptions = null)SaveResultUpdates a single record
Edit<T>(IEnumerable<T> models, DatabaseOptions dbOptions = null)IEnumerable<SaveResult>Updates multiple records in a single bulk operation
Database.EditAsync(dbObject model)Task<SaveResult>Async single-record update.
Database.EditAsync<T>(IEnumerable<T> records)Task<IEnumerable<SaveResult>>Async bulk update.

Upsert Methods

Upsert methods insert new records or update existing records based on matching criteria.

Method SignatureReturn TypeDescription
Upsert(dbObject model, DatabaseOptions dbOptions = null)SaveResultInserts or updates a single record based on ID or external ID match
Upsert<T>(IEnumerable<T> models, DatabaseOptions dbOptions = null)IEnumerable<SaveResult>Inserts or updates multiple records in a single bulk operation
Database.UpsertAsync(dbObject model)Task<SaveResult>Async single-record insert-or-update.
Database.UpsertAsync(IEnumerable<dbObject> records)Task<IEnumerable<SaveResult>>Async bulk upsert.

Delete Methods

Delete methods remove records from the database.

Method SignatureReturn TypeDescription
Delete(string id, DatabaseOptions dbOptions = null)DeleteResultDeletes a single record by its ID
Delete(dbObject model, DatabaseOptions dbOptions = null)DeleteResultDeletes a single record
Delete<T>(IEnumerable<T> models, DatabaseOptions dbOptions = null)IEnumerable<DeleteResult>Deletes multiple records in a single bulk operation
Database.DeleteAsync(dbObject model)Task<DeleteResult>Async single-record delete (soft delete by default).
Database.DeleteAsync(string id)Task<DeleteResult>Async delete by record ID.
Database.DeleteAsync(IEnumerable<dbObject> records)Task<IEnumerable<DeleteResult>>Async bulk delete.

Utility Methods

Utility methods provide additional database functionality.

Method SignatureReturn TypeDescription
Restore(string id)voidRestores a soft-deleted record from the recycle bin

QueryFlex Method

QueryFlex performs aggregate queries with GROUP BY support, returning dynamic results for unpredictable data structures.

Method SignatureReturn TypeDescription
QueryFlex(string queryString, params object[] parameters)dynamicExecutes aggregate queries with GROUP BY, returning dynamic objects

Async Method Variants

Almost every Database operation has an asynchronous counterpart that returns a Task rather than blocking the request thread. Async variants are required in AspxAsyncController actions (which must be fully async) and recommended in any I/O-heavy code path in AspxController or Active Class code.

Most async variants are drop-in replacements: the method name is the sync name plus Async (or the AsAdmin suffix becomes AsAdminAsync). The return type is wrapped in Task<T>.

SyncAsync equivalent
query.ToList()await query.ToListAsync()
query.ToListAsAdmin()await query.ToListAsAdminAsync()
query.First()await query.FirstAsync()
query.FirstAsAdmin()await query.FirstAsAdminAsync()
query.Count()await query.CountAsync()
query.CountAsAdmin()await query.CountAsAdminAsync()
Database.Retrieve<T>(id)await Database.RetrieveAsync<T>(id)
Database.Create(record)await Database.CreateAsync(record)
Database.Edit(model)await Database.EditAsync(model)
Database.Upsert(model)await Database.UpsertAsync(model)
Database.Delete(model)await Database.DeleteAsync(model)

Example — async controller action returning IrisData:

public class ContactApiController : AspxAsyncController
{
    [Authorize]
    public async Task<ActionResponse> GetByAccount(string accountId)
    {
        if (string.IsNullOrEmpty(accountId))
            throw new ModelValidationException("accountId is required.");

        var contacts = await Database.Query<Contact>()
            .Where(c => c.AccountId == accountId)
            .OrderBy(c => c.LastName)
            .ToListAsync();

        return IrisData(new { contacts }, With.Update | With.Delete);
    }
}

Async create followed by an async edit:

[Authorize]
public async Task<ActionResponse> CreateAndAssign(Contact model, string ownerId)
{
    if (string.IsNullOrWhiteSpace(model.LastName))
        throw new ModelValidationException("Last name is required.");

    await Database.CreateAsync(model);

    model.OwnerId = ownerId;
    await Database.EditAsync(model);

    return IrisData(new { contact = model });
}

Running independent queries in parallel:

public async Task<ActionResponse> Dashboard(string accountId)
{
    var accountTask = Database.RetrieveAsync<Account>(accountId);
    var contactsTask = Database.Query<Contact>()
        .Where(c => c.AccountId == accountId)
        .ToListAsync();
    var opportunityCountTask = Database.Query<Opportunity>()
        .Where(o => o.AccountId == accountId)
        .CountAsync();

    await Task.WhenAll(accountTask, contactsTask, opportunityCountTask);

    return IrisData(new
    {
        account = accountTask.Result,
        contacts = contactsTask.Result,
        opportunityCount = opportunityCountTask.Result
    });
}

When to choose async:

  • Required: Actions on AspxAsyncController — every action must be async Task<ActionResponse>.
  • Recommended: Long-running or I/O-bound code paths in any controller. Async releases the request thread while the database or external call is in flight.
  • Required for parallel work: When fetching multiple independent results, async lets you start the queries together and await Task.WhenAll(...) to wait for all of them concurrently.
  • Optional: Short, simple, CPU-bound logic or one-off Setup-area handlers that already run synchronously can stay sync. Mixing sync and async unnecessarily adds noise without measurable benefit.

Common pitfalls:

  • Do not call .Result or .Wait() on a Task in a controller action. Doing so blocks the thread and can deadlock the request pipeline. Always await.
  • Mark the action async. Calling an async method without await returns a Task object instead of the actual result.
  • Cancel-safe by default. The platform handles request cancellation; you do not need to thread CancellationToken through routine queries.

Method Naming Conventions

Create vs Insert: The Database class uses Create() for insert operations, not Insert(). This aligns with Magentrix terminology where "Create" represents the action of adding new records to the database.

Edit vs Update: The Database class uses Edit() for update operations, not Update(). This aligns with Magentrix terminology where "Edit" represents the action of modifying existing records.

Generic Type Parameter: Methods with generic type parameter <T> return strongly-typed results. Methods without generic parameters work with the base dbObject type and are useful when entity types are determined dynamically at runtime.

Overloads for Single and Bulk: Create, Edit, Upsert, and Delete methods provide overloads for both single-record and bulk operations. Always use the bulk overload when working with multiple records to optimize performance and reduce database round trips.

Common Parameters

func (Expression<Func<T, bool>>): A LINQ expression that defines filtering criteria. Example: f => f.Name.Contains("Test") && f.IsActive == true

relationship (Expression<Func<T, object>>): A LINQ expression specifying the related entity to eager load. Example: r => r.Account

fields (Expression<Func<T, object>>): A LINQ expression specifying which fields to load. Example: f => new { f.Id, f.Name, f.Type }

dbOptions (DatabaseOptions): Controls database operation behavior including system mode, transactional processing, and error handling mode.

Return Type Details

SqlExpressionVisitor<T>: Query methods return SqlExpressionVisitor<T> which supports LINQ method chaining. Call .ToList(), .First(), or .Count() to execute the query.

// Query returns SqlExpressionVisitor<Account>
var query = Database.Query<Account>()
    .Where(f => f.Type == "Partner")
    .OrderBy(f => f.Name);

// Execute query
var accounts = query.ToList();  // Returns List<Account>

SaveResult: Contains operation results for Create, Edit, and Upsert operations including the record ID, error status, error messages, and timestamp. See Working with Database Results for complete reference.

DeleteResult: Contains operation results for Delete operations including error status and error messages. See Working with Database Results for complete reference.

IEnumerable<SaveResult> / IEnumerable<DeleteResult>: Bulk operations return collections of results, one for each record processed.

Usage Notes

Method Chaining: Query methods returning SqlExpressionVisitor<T> support LINQ method chaining. Chain methods in any order—the query is only executed when you call .ToList(), .ToListAsAdmin(), .First(), .FirstAsAdmin(), .Count(), or .CountAsAdmin().

Execution Context: All methods execute in the security context of the current user unless using .ToListAsAdmin(), .FirstAsAdmin(), or .CountAsAdmin() extension methods, which execute with system privileges.

Transaction Support: Operations support transactional execution using AllOrNone = true in DatabaseOptions, ensuring all records succeed or all fail together.

Error Handling: By default, operations throw exceptions on error. Set IsApiMode = true in DatabaseOptions to return errors in results without throwing exceptions.

Query Execution: Queries are lazy-evaluated. The actual database query executes only when you call .ToList(), .ToListAsAdmin(), .First(), .FirstAsAdmin(), .Count(), .CountAsAdmin(), or iterate over the results.

// Query not yet executed
var query = Database.Query<Account>()
    .Where(f => f.Type == "Partner")
    .OrderBy(f => f.Name)
    .Limit(50);

// Query executes here
var accounts = query.ToList();
Last updated on 5/26/2026

Attachments