EAV Metadata Manipulation
When interacting with fields defined as type Metadata in the Schema, you are interacting with an Entity-Attribute-Value (EAV) storage model.
In C#, these dynamic attributes are not direct properties on the entity. Instead, they are housed in an internal collection named MetadataEntries. The system provides a strongly-typed proxy property named after your field, which filters the entries for that specific metadata dictionary.
The underlying class is always generated as {EntityName}_Metadata. The values are strongly typed into physical database columns: StringValue, NumberValue, BoolValue, and DateValue.
Safely Reading a Metadata Attribute
To read a dynamic property, you must search the collection for the AttributeName.
// Example: Entity is 'Product', Metadata Field is 'CustomSpecs'
var voltageEntry = Entity.CustomSpecs.FirstOrDefault(m => m.AttributeName == "Voltage");
if (voltageEntry != null && voltageEntry.NumberValue > 240m)
{
AddError("CustomSpecs", "Voltage cannot exceed 240V.");
}
Writing to a Metadata Attribute
To modify or add new keys via a script, you must check if the entry exists. If it does not, you instantiate a new EAV object and add it to the MetadataEntries base collection.
// Example: Entity is 'Product', Metadata Field is 'CustomSpecs'
var reviewEntry = Entity.CustomSpecs.FirstOrDefault(m => m.AttributeName == "ReviewedBy");
if (reviewEntry == null)
{
// The type is always named {EntityName}_Metadata
reviewEntry = new Struktural.Generated.Product_Metadata
{
FieldName = "CustomSpecs", // Must match the property name exactly
AttributeName = "ReviewedBy"
};
// Add to the base collection to ensure EF Core tracks the insertion
Entity.MetadataEntries.Add(reviewEntry);
}
// Assign to the appropriate typed property
reviewEntry.StringValue = User.Identity?.Name ?? "System";