Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Orbis25/FoundationKit/llms.txt

Use this file to discover all available pages before exploring further.

Every entity in a FoundationKit application starts from one of two abstract base classes: BaseModel or BaseBasicModel. These classes live in the FoundationKit.Domain.Models namespace and give every table a consistent, predictable shape — a stable primary key, creation and update timestamps, a soft-delete flag, and optional audit fields that record who created or last modified a record. By inheriting from one of these classes instead of writing those fields by hand each time, you get repository support, soft-delete behaviour, and pagination for free, because FoundationKit’s generic repository types are constrained to BaseModel.

Properties at a glance

The following table lists every property defined across BaseModel and BaseBasicModel, its type, whether it is persisted by EF Core, and what it is used for.
PropertyTypePersistedDescription
IdGuid✅ YesPrimary key. Generated by the application layer before insert.
CreatedAtDateTime✅ YesTimestamp set when the record is first created.
UpdatedAtDateTime?✅ YesTimestamp to be set on updates. Nullable — null means never updated. Must be set by the application layer; the base class does not auto-populate it.
IsDeletedbool✅ YesSoft-delete flag. true means the record is logically deleted but still present in the database.
CreatedBystring?✅ Yes (BaseModel) / ❌ No (BaseBasicModel)Identifier of the user who created the record.
UpdatedBystring?✅ Yes (BaseModel) / ❌ No (BaseBasicModel)Identifier of the user who last updated the record.
CreatedAtStrstring[NotMapped]Computed display string: CreatedAt formatted as dd/MM/yyyy hh:mm:ss.
UpdateAtStrstring[NotMapped]Computed display string: UpdatedAt formatted as dd/MM/yyyy hh:mm:ss, or "" if null.

BaseModel

BaseModel is the root abstract class. Inherit from it when you need full audit tracking — the CreatedBy and UpdatedBy columns are mapped to real database columns, so you can query which user created or modified any row.
// FoundationKit.Domain/Models/BaseModel.cs
public abstract class BaseModel
{
    public virtual Guid Id { get; set; }

    public virtual DateTime CreatedAt { get; set; }

    /// <summary>
    /// If you after used updateAt please override this prop
    /// and add annotation [Column("UpdateAt")]
    /// </summary>
    public virtual DateTime? UpdatedAt { get; set; }

    [NotMapped]
    public string CreatedAtStr => CreatedAt.ToString("dd/MM/yyyy hh:mm:ss");

    [NotMapped]
    public string UpdateAtStr => UpdatedAt != null
        ? UpdatedAt.Value.ToString("dd/MM/yyyy hh:mm:ss")
        : "";

    public virtual bool IsDeleted { get; set; }

    public virtual string? CreatedBy { get; set; }

    public virtual string? UpdatedBy { get; set; }
}

Inheriting BaseModel

Declare your entity class as public class MyEntity : BaseModel and add only the domain-specific properties. EF Core will migrate Id, CreatedAt, UpdatedAt, IsDeleted, CreatedBy, and UpdatedBy as real columns.
using FoundationKit.Domain.Models;

public class Invoice : BaseModel
{
    public string? InvoiceNumber { get; set; }
    public decimal Amount { get; set; }
    public string? CustomerId { get; set; }
}
The resulting table will have columns: Id, CreatedAt, UpdatedAt, IsDeleted, CreatedBy, UpdatedBy, InvoiceNumber, Amount, CustomerId.

BaseBasicModel

BaseBasicModel extends BaseModel but overrides CreatedBy and UpdatedBy with the [NotMapped] attribute. The properties still exist on the C# object — you can assign them freely at runtime — but EF Core will not create or write to CreatedBy/UpdatedBy columns in the database. This is the right choice for tables where audit trail by user is unnecessary and you want to keep the schema lean.
// FoundationKit.Domain/Models/BaseBasicModel.cs
public abstract class BaseBasicModel : BaseModel
{
    [NotMapped]
    public override string? CreatedBy { get; set; }

    [NotMapped]
    public override string? UpdatedBy { get; set; }
}

Inheriting BaseBasicModel

using FoundationKit.Domain.Models;

public class Category : BaseBasicModel
{
    public string? Name { get; set; }
    public string? Slug { get; set; }
}
The resulting table will have columns: Id, CreatedAt, UpdatedAt, IsDeleted, Name, Slug — no audit columns.
BaseModel vs BaseBasicModel — which should I use?Choose BaseModel when you need to persist who created or last modified a record (e.g. orders, invoices, user-generated content). Choose BaseBasicModel when the entity is managed by the system rather than individual users (e.g. lookup tables, categories, configuration records) and you want to avoid the overhead of tracking audit columns in the database. Both expose the same Id, CreatedAt, UpdatedAt, and IsDeleted fields.

Soft-delete with IsDeleted

FoundationKit treats deletion as a state change rather than a destructive operation. When you call SoftRemoveAsync on a repository, the entity row is not removed from the database. Instead, the IsDeleted flag is set to true and the change is committed inside a transaction.
// The repository sets IsDeleted = true and commits — no DELETE SQL is issued.
await _personService.SoftRemoveAsync(personId, cancellationToken);
Filtered queries in your application should always include a .Where(x => !x.IsDeleted) predicate (or use a global query filter in your DbContext) to ensure soft-deleted records do not appear in results. If you genuinely need to erase a row from the database, call RemoveAsync instead, which issues a real DELETE.

Computed [NotMapped] display strings

CreatedAtStr and UpdateAtStr are convenience properties intended for serialisation scenarios where you want a pre-formatted, human-readable date string instead of a raw DateTime. Because they carry [NotMapped], EF Core never attempts to read them from or write them to the database — they are computed on the fly from CreatedAt and UpdatedAt respectively.
var person = await _personService.GetByIdAsync(id);

Console.WriteLine(person.CreatedAtStr);  // e.g. "14/02/2025 03:45:22"
Console.WriteLine(person.UpdateAtStr);   // e.g. "15/02/2025 09:10:05" or ""
These same properties are exposed through BaseOutput so they appear automatically in your API responses without any additional mapping configuration.

Build docs developers (and LLMs) love