Magentrix Trigger Lifecycle & Code Structure
Magentrix Trigger Lifecycle & Code Structure
In Magentrix, triggers are used to execute custom logic before or after changes are made to records in the system. This guide explains the structure and lifecycle of a trigger using a sample trigger class: LeadTrigger.
Trigger Structure
Every Magentrix trigger inherits from ActiveTrigger<T>, where T is the entity type (e.g., Lead, Account, etc.). The primary method you override is Execute(TransactionContext<T> trigger), which receives a TransactionContext containing the list of records involved in the operation and transaction metadata.
public class LeadTrigger : ActiveTrigger<Lead>
{
public override void Execute(TransactionContext<Lead> trigger)
{
// Logic goes here
}
}
Trigger Lifecycle Overview
Triggers in Magentrix are executed in two phases:
1. Before Events (trigger.IsBefore)
These events occur before the database transaction is committed. They allow you to validate, modify, or prevent data changes. Only native Magentrix entities support before-triggers.
a. Before Insert
if (trigger.IsInsert)
{
foreach (var rec in trigger.Records)
{
SystemInfo.Debug($"[Before Insert] Creating record: {rec.New.Name}");
}
}
b. Before Update
if (trigger.IsUpdate)
{
foreach (var rec in trigger.Records)
{
SystemInfo.Debug($"[Before Update] New: {rec.New.Name} | Old: {rec.Old.Name}");
}
}
c. Before Delete
if (trigger.IsDelete)
{
foreach (var rec in trigger.Records)
{
SystemInfo.Debug($"[Before Delete] Deleting record: {rec.Old.Id}");
}
}
2. After Events (trigger.IsAfter)
These events execute after the transaction is committed. They are available for both native and CRM-synced records.
a. After Insert
if (trigger.IsInsert)
{
foreach (var rec in trigger.Records)
{
SystemInfo.Debug($"[After Insert] Created record: {rec.New.Id}");
}
}
b. After Update
if (trigger.IsUpdate)
{
foreach (var rec in trigger.Records)
{
SystemInfo.Debug($"[After Update] New: {rec.New.Name} | Old: {rec.Old.Name}");
}
}
c. After Delete (Not available for CRM entities)
if (trigger.IsDelete)
{
foreach (var rec in trigger.Records)
{
SystemInfo.Debug($"[After Delete] Deleted record: {rec.Old.Id}");
}
}
Here is the complete Sample of the Life Cycle
public class LeadTrigger : ActiveTrigger<Lead>
{
public override void Execute(TransactionContext<Lead> trigger)
{
if (trigger.IsBefore)
{
// This block is only called for Magentrix native entities
// It allows actions before a record is committed to the database
if (trigger.IsDelete)
{
// This runs before deleting a native record
// Only rec.Old is populated (rec.New is always null)
foreach (var rec in trigger.Records)
{
SystemInfo.Debug($"[Before Delete] Deleting record: {rec.Old.Id}");
}
}
if (trigger.IsInsert)
{
// Runs before inserting a native record
// Only rec.New is populated (rec.New.Id is empty at this point)
foreach (var rec in trigger.Records)
{
SystemInfo.Debug($"[Before Insert] Creating record: {rec.New.Name}");
}
}
if (trigger.IsUpdate)
{
// Runs before updating a native record
// rec.Old = original record, rec.New = updated values
foreach (var rec in trigger.Records)
{
SystemInfo.Debug($"[Before Update] New: {rec.New.Name} | Old: {rec.Old.Name}");
}
}
}
if (trigger.IsAfter)
{
// This block runs after the transaction has been committed
// It applies to both native and CRM-synced entities
if (trigger.IsDelete)
{
// Runs after deleting a native record
foreach (var rec in trigger.Records)
{
SystemInfo.Debug($"[After Delete] Deleted record: {rec.Old.Id}");
}
}
if (trigger.IsInsert)
{
// Runs after inserting a native or CRM record
// rec.New.Id is now available
foreach (var rec in trigger.Records)
{
SystemInfo.Debug($"[After Insert] Created record: {rec.New.Id}");
}
}
if (trigger.IsUpdate)
{
// Runs after updating a native or CRM record
foreach (var rec in trigger.Records)
{
SystemInfo.Debug($"[After Update] New: {rec.New.Name} | Old: {rec.Old.Name}");
}
}
}
}
}
Here is a Sample Code For this Video
public class HotDealTrigger : ActiveTrigger<Lead>
{
public override void Execute(TransactionContext<Lead> trigger)
{
if (trigger.IsAfter)
{
if (trigger.IsInsert || trigger.IsUpdate)
{
var accountIds = trigger.Records.Where (a => !string.IsNullOrEmpty(a.New.PartnerAccountId)).Select(a => a.New.PartnerAccountId).ToList();
if (accountIds.Count > 0)
{
var accounts = Database.Query<Account>(a => accountIds.Contains(a.Id)).ToListAsAdmin();
var ownerIds = accounts.Select(a => a.OwnerId).ToList();
var owners = Database.Query<User>(a => ownerIds.Contains(a.Id)).ToListAsAdmin();
foreach (var rec in trigger.Records.Where(a => !string.IsNullOrEmpty(a.New.PartnerAccountId)))
{
var account = accounts.FirstOrDefault(a => a.Id == rec.New.PartnerAccountId);
if (account == null) continue;
var owner = owners.FirstOrDefault(a => a.Id == account.OwnerId);
if (owner == null || !string.IsNullOrEmpty(owner.MobilePhone)) continue;
var twilio = new Messaging.Twilio("your_config_name");
twilio.SendSMS(owner.MobilePhone, $"You have a hot deal: {SystemInfo.Company.OrgURL}/{rec.New.Id}");
}
}
}
}
}
}
Key Concepts
Concept | Description |
|---|
trigger.IsBefore | Executes before database changes. Only for native entities. |
trigger.IsAfter | Executes after database changes. Works for both native and CRM entities. |
trigger.IsInsert | Indicates a create operation. |
trigger.IsUpdate | Indicates an update operation. |
trigger.IsDelete | Indicates a delete operation. (Not supported for CRM entities) |
rec.New | Represents the new state of the record (for insert/update). |
rec.Old | Represents the original state of the record (for update/delete). |
Example Use Cases
Trigger Phase | Operation | Common Use Cases |
|---|
Before | Insert | Default value population, validation logic |
Before | Update | Field-level security, change logging |
Before | Delete | Preventing deletion of critical records |
After | Insert | Notifications, integrations, audit trails |
After | Update | Sync with external tools, workflow triggers |
After | Delete | Cleanup tasks, external system updates |
Best Practices
Use Before triggers for validation and data manipulation.
Use After triggers for integrations, logging, and asynchronous workflows.
Always check both trigger.IsBefore/IsAfter and IsInsert/Update/Delete to avoid unintended behavior.
Be mindful of system performance—avoid heavy operations inside triggers.