Acumatica DAC Extensions Best Practices
Introduction
Data Access Class (DAC) Extensions are one of the most powerful features in Acumatica for customizing the platform. They allow you to add custom fields to existing tables without modifying the core codebase, making upgrades easier and maintenance simpler.
In this guide, we'll explore best practices for creating and managing DAC Extensions in Acumatica, ensuring your customizations are maintainable, performant, and upgrade-safe.
Understanding DAC Extensions
A DAC Extension is a class that extends an existing DAC, adding new fields or overriding existing behavior. Extensions use the PXCacheExtension attribute to link to the base DAC:
[Serializable]
public class CustomerMaintExt : PXCacheExtension
{
[PXString(50)]
[PXUIField(DisplayName = "Custom Field")]
public string UsrCustomField { get; set; }
public abstract class usrCustomField :
PX.Data.BQL.BqlString.Field { }
}
The key components are the field property, the abstract field class, and the PXUIField/PXDBField attributes for configuration.
Field Types and Definitions
Choose the appropriate field type based on your data requirements:
- PXString - For text fields (with length parameter)
- PXInt, PXLong, PXDecimal, PXDouble - For numeric fields
- PXBool - For boolean values
- PXDate - For date fields
- PXGuid - For unique identifiers
// String field with max length
[PXString(100)]
[PXUIField(DisplayName = "Company Name")]
public string UsrCompanyName { get; set; }
// Decimal field for currency
[PXDecimal(2)]
[PXUIField(DisplayName = "Credit Limit")]
public decimal? UsrCreditLimit { get; set; }
// Boolean field
[PXBool]
[PXUIField(DisplayName = "Active")]
public bool? UsrIsActive { get; set; }
Creating Extension Classes
Follow these steps to create a proper DAC Extension:
// Step 1: Define the extension class
[Serializable]
public class SOOrderExt : PXCacheExtension
{
// Step 2: Add field properties
[PXString(50)]
[PXUIField(DisplayName = "Project Code")]
public string UsrProjectCode { get; set; }
public abstract class usrProjectCode :
PX.Data.BQL.BqlString.Field { }
}
// Step 3: Subscribe to events in graph extension
public class SOOrderEntry_Extension : PXGraphExtension
{
protected void SOOrder_RowUpdated(PXCache sender,
PXRowUpdatedEventArgs e)
{
var row = (SOOrder)e.Row;
var ext = row.GetExtension();
// Custom logic here
}
}
Validation and Events
Implement validation using field-level and row-level events:
// Field-level validation
protected void SOOrder_UsrProjectCode_FieldVerifying(
PXCache sender, PXFieldVerifyingEventArgs e)
{
var newValue = (string)e.NewValue;
if (!string.IsNullOrEmpty(newValue) && newValue.Length < 5)
{
throw new PXSetPropertyException(
"Project code must be at least 5 characters");
}
}
// Row-level validation
protected void SOOrder_RowPersisting(PXCache sender,
PXRowPersistingEventArgs e)
{
var row = (SOOrder)e.Row;
var ext = row.GetExtension();
if (string.IsNullOrEmpty(ext.UsrProjectCode))
{
sender.RaiseExceptionHandling(
row, null, new PXSetPropertyException(
"Project code is required"));
}
}
Best Practices
- Use proper naming conventions - Prefix custom fields with "Usr"
- Always define abstract fields - Required for field references
- Use appropriate field types - Match data type to business need
- Implement validation early - Validate at field level when possible
- Document custom fields - Keep documentation for upgrades
- Test thoroughly - Test all scenarios and edge cases
- Consider upgrade impact - Avoid overriding core behavior
Summary
DAC Extensions are essential for customizing Acumatica while maintaining upgrade compatibility. By following these best practices, you can create robust customizations that are maintainable and stable.
For more information, check out our other tutorials on Acumatica Customization Basics and Custom Screens.