Properties
Properties define the data fields on an entity. Each property requires a [Property<T>] attribute that specifies the data type and a display label.
[Property<T>("Label")]
The generic type parameter T is a data type that controls validation, formatting, and database column type. The string argument is the human-readable label.
[Property<DataTypes.Text>("Name")]
public partial string Name { get; set; }
Properties must be partial — the source generator provides the implementation with change tracking and event hooks.
Optional Parameters
| Parameter | Type | Description |
|---|---|---|
Description |
string? |
User-facing description explaining the property's purpose |
Technical |
string? |
Internal notes for developers (not shown to end users) |
[Property<DataTypes.ProperNoun>("Full name",
Technical = "Cached property from PrimaryContact.FullName so that we do a full-text search.")]
public partial string FullName { get; }
Common Data Types
| Data Type | CLR Type | Example |
|---|---|---|
DataTypes.Text |
string |
Names, short text (max 100) |
DataTypes.IdText |
string |
IDs, SKUs — uppercase, barcode-safe (max 15) |
DataTypes.MultilineText |
string |
Long descriptions, notes (unlimited) |
DataTypes.ProperNoun |
string |
People/business names — auto title-cased (max 50) |
DataTypes.Integer |
int |
Whole numbers |
DataTypes.Decimal |
decimal |
Numbers with 2 decimal places |
DataTypes.Currency |
decimal |
Money values (2 decimals) |
DataTypes.Boolean |
bool |
True/false flags |
DataTypes.DateOnly |
DateOnly? |
Dates without time |
DataTypes.DateTime |
DateTime? |
Date and time |
DataTypes.Enum |
TEnum |
Any C# enum |
See Data Types for the complete list.
[Required]
Marks a property as non-nullable. The value must be provided before saving.
[Required]
[Property<DataTypes.IdText>("SKU")]
public partial string Sku { get; set; }
[MaxLength(n)]
Overrides the data type's default maximum length. Only applies to string properties.
[MaxLength(20)]
[Property<DataTypes.IdText>("SKU")]
public partial string Sku { get; set; }
If omitted, the data type's default max length is used (e.g., IdText defaults to 15, Text defaults to 100).
[DefaultValue(...)]
Sets the initial value when a new entity is created. Uses System.ComponentModel.DefaultValueAttribute.
using System.ComponentModel;
[Property<DataTypes.Text>("Color")]
[DefaultValue("#ffffff")]
public partial string Color { get; set; }
[Property<DataTypes.Enum>("Status")]
[DefaultValue(SalesOrderStatus.Open)]
public partial SalesOrderStatus Status { get; set; }
[DefaultValue(1)]
[Property<DataTypes.PositiveDecimal>("Factor")]
public partial decimal Factor { get; set; }
Read-Only Properties
Use { get; } (no setter) for computed properties whose value is set by business logic:
[Property<DataTypes.ProperNoun>("Full name")]
public partial string FullName { get; }
[Virtual]
[Property<DataTypes.Currency>("Total Price")]
public partial decimal TotalPrice { get; }
Read-only properties are typically populated by Compute events in business logic.
[Virtual] on Properties
Marks a property as computed — it is not persisted to the database. The value is calculated at runtime by business logic.
[Virtual]
[Property<DataTypes.Currency>("Subtotal")]
public partial decimal Subtotal { get; }
[Virtual]
[Property<DataTypes.Currency>("Total")]
public partial decimal Total { get; }
Virtual properties:
- Have no database column
- Are recalculated when their dependencies change
- Are typically read-only (
{ get; }) - Can also be read-write (
{ get; set; }) for user-editable computed values
// Virtual but editable — user can override the computed value
[Virtual]
[Property<DataTypes.Decimal>("Quantity")]
public partial decimal QuantityUom { get; set; }
Custom Data Types on Properties
You can use domain-specific data types defined in your project (see Creating Data Types):
[Property<ProductUnitPrice>("Cost",
Description = "The cost of the product")]
public partial decimal Cost { get; set; }
[Property<ProductQuantity>("Quantity (Each)")]
public partial decimal Quantity { get; set; }
Complete Example
using System.ComponentModel;
namespace Benevia.ERP.Model.Products;
[ApiEntity]
[NaturalKey(nameof(Sku))]
public partial class Product : EntityBase
{
[Required]
[MaxLength(20)]
[Searchable(1, Dictionary = "simple")]
[Property<DataTypes.IdText>("SKU",
Description = "Your part number for this product")]
public partial string Sku { get; set; }
[Searchable(2)]
[Property<DataTypes.MultilineText>("Description",
Description = "The description of the product that is used in sales documents.")]
public partial string SalesDescription { get; set; }
[Property<DataTypes.Decimal>("Unit weight")]
public partial decimal UnitWeight { get; set; }
[Property<ProductUnitPrice>("Cost",
Description = "The cost of the product. This is often used to calculate the price")]
public partial decimal Cost { get; set; }
[Property<DataTypes.Website>("Website")]
public partial string Website { get; set; }
[Property<DataTypes.Text>("Color")]
[DefaultValue("#ffffff")]
public partial string Color { get; set; }
// Virtual — computed, not in database
[Virtual]
[Property<DataTypes.Boolean>("Require all units to be sold in integer quantities")]
public partial bool RequireIntegerQuantitiesForAllUOMs { get; set; }
}