Some of Acumatica field attributes are responsible for the same DAC field's behavior. They basically configure the same aspect of a DAC field but in a different way. For example, both PXDBInt and PXDBString attributes configure the mapping between the type of data stored in the DAC field and in the corresponding database column. One basically tells the runtime that it should treat the data from the DB column as an int number and the other tells the runtime to treat as string. It is easy to see that such attributes don't live well with each other if they are declared on the same DAC field. Most likely, they will interfere with each other and the resulting DAC field behavior will be messed up.
To address this issue Acumatica Framework introduced for DAC field attributes a concept of the attribute family.
Attribute family is a set of DAC field attributes responsible for the same aspect of the DAC field's behavior. All such attributes are annotated with the
PX.Data.PXAttributeFamily attribute:
https://beacon.acumatica.com/h/DHn_v7W2IfrmpF0TVXpmPg/api/PX.Data.PXAttributeFamilyAttribute.html.
Acumatica Framework uses this attribute in its different parts to either make sure that field attributes from the same family are not used together, or to determine whether two DAC field attributes have equivalent attribute types.
PXAttributeFamily Attribute and Root Types
The key part of the Acumatica attributes family mechanism is the PX.Data.PXAttributeFamily attribute: https://beacon.acumatica.com/h/DHn_v7W2IfrmpF0TVXpmPg/api/PX.Data.PXAttributeFamilyAttribute.html
It is used to annotate DAC field attributes from the same family. The annotation looks like this.
[PXAttributeFamily(typeof(PXFieldState))]
public class PXLongAttribute : PXEventSubscriberAttribute, ...
{...}
As you can see, the PXAttributeFamily attribute accepts a single type parameter. This type parameter is called Root Type and it serves as a marker that distinguishes one family of DAC field attributes from another attributes family. Any type can be a Root Type. Usually, for attributes family related to some particular aspect of DAC fields behavior, a Root Type related to that behavior is used. For example, the PXFieldState type is heavily used in the part of Acumatica Framework responsible for the display of DAC field's value in the UI. Thus it is used as a Root Type for the family of attributes configuring the display of DAC field's value in the UI. The PXLong attribute from the example above belongs to this attributes family.
DAC Field Attributes and Attribute Families
As you have read in the previous section, an attribute family is defined by its Root Type. A DAC field attribute is considered to belong to the attribute family with a particular Root Type in two cases:
- It has the
PXAttributeFamily attribute with that particular Root Type declared on it. - One of its base attribute types has the
PXAttributeFamily attribute with that particular Root Type declared on it.
This means that you can declare the PXAttributeFamily attribute on a base DAC field attributes and all field attributes derived from it will belong to the same attributes family.
The DAC field attribute is not limited to just one attributes family. It can belong to multiple different families with different Root Types. For example, here is the PXDBFieldAttribute, the base attribute for all data type field attributes such as PXDBInt that specify both how DAC field's value is mapped to the corresponding DB column and how it is displayed in the UI:
[PXAttributeFamily(typeof(PXDBFieldAttribute))]
[PXAttributeFamily(typeof(PXFieldState))]
public class PXDBFieldAttribute : PXEventSubscriberAttribute, ...
{}
This makes attributes such as PXDBInt and PXDBString part of the same attributes family which means that they shouldn't be placed together on the same DAC field. All of this leads to the most important rule about the attribute families.
| You must not declare on the same DAC field multiple DAC field attributes that belong to the same attributes family (the attributes family with the same Root Type). This also means that a DAC field attribute can be applied to a DAC field only once, if it belongs to some attributes family. |
Example of Attribute Families