Added Event
Summary
The Added event fires when a new entity instance is created in a data context. Use it to initialize dynamic properties, create related child entities, or perform setup logic that depends on runtime data (such as the current date or user).
When does it fire?
The Added event fires when new Entity(context) is called — that is, when a new entity is constructed with an EventContext or IDataContext. It runs once per entity creation.
Syntax
salesOrder.OnAdded().Do((entity, args) => { /* logic */ });
Do overloads
| Signature | Description |
|---|---|
.Do(entity => { }) |
Run logic with access to the entity |
.Do((entity, args) => { }) |
Run logic with access to the entity and services/data via args |
Scenarios
1. Setting the order date to today
When a new sales order is created, default the order date to the current date.
[Logic]
public class SalesOrderBL(SalesOrder.Logic salesOrder)
{
[RegisterLogic]
public void SetOrderDate()
{
salesOrder.OnAdded().Do(o =>
o.OrderDate = DateOnly.FromDateTime(DateTime.UtcNow));
}
}
Note: Do NOT use
OnAddedfor static default values likeQuantity = 1. Use the[DefaultValue(1)]attribute instead.
2. Creating a main UOM when a product is created
When a new product is created, automatically add its main unit of measure if one does not already exist.
[Logic]
public class ProductBL(Product.Logic product)
{
[RegisterLogic]
public void CreateMainUom()
{
product.OnAdded().Do((p, args) =>
{
if (p.Uoms.Count == 0 || !p.Uoms.Any(u => u.Operation == UomOperation.Main))
{
var context = args.Context;
var mainUom = new ProductUom(context)
{
Product = p,
Factor = 1,
Operation = UomOperation.Main,
SellableOption = SellableOption.DefaultSellingUnit
};
}
});
}
}
3. Initializing a newly created customer
When a new customer is created, set up initial properties based on the environment.
[Logic]
public class CustomerBL(Customer.Logic customer)
{
[RegisterLogic]
public void InitializeNewCustomer()
{
customer.OnAdded().Do((c, args) =>
{
c.CreatedDate = DateOnly.FromDateTime(DateTime.UtcNow);
c.Status = CustomerStatus.Active;
});
}
}
4. Copying defaults from a parent entity
When a new sales order detail is added, carry forward settings from the order header.
[Logic]
public class SalesOrderDetailBL(SalesOrderDetail.Logic salesOrderDetail)
{
[RegisterLogic]
public void InheritOrderDefaults()
{
salesOrderDetail.OnAdded().Do((detail, args) =>
{
if (detail.SalesOrder != null)
detail.DiscountPercent = detail.SalesOrder.DefaultDiscountPercent;
});
}
}
5. Using a service to generate an ID on creation
When a contact is created, generate a unique ID using a sequence manager.
[Logic]
public class ContactBL(Contact.Logic contact)
{
[RegisterLogic]
public void GenerateContactId()
{
contact.OnAdded().Do((c, args) =>
{
var sequenceManager = args.GetService<ISequenceManager>();
var nextVal = sequenceManager.GetNextSequenceValueAsync("ContactSequence").Result;
c.Id = $"C-{nextVal:D6}";
});
}
}
Notes
OnAddedfires once on entity construction — it does not fire when loading an existing entity from the database.- Use
OnAddedfor dynamic defaults that depend on runtime context (current date, services, parent entity data). - For static literal defaults (e.g.,
Factor = 1), use the[DefaultValue]attribute on the property. OnAddedhas access toargs.Context,args.GetService<T>(), andargs.GetEntities<T>().