-
Notifications
You must be signed in to change notification settings - Fork 226
Settings.ForeignKeyAnnotationsProcessing
Adds attributes to navigation properties, chosen per relationship.
| Type | Func<Table, Table, string, string, string[]> |
| Parameters | (fkTable, pkTable, propName, fkPropName) |
| Returns | Attribute names without brackets, or null for none |
| Default | Returns null
|
| Applies to | EF 6 and EF Core |
| Databases | All |
In Database.tt? |
Yes, with a commented-out example |
Navigation properties are the ones that break serialisation. Product.Category points at a Category, whose
Products collection points back at the Product, and a naive JSON serialiser follows that cycle until it
gives up. The usual fix is [JsonIgnore], and this is how you apply it selectively.
The callback runs per relationship and returns an array of attribute names. The generator wraps each in
brackets and writes it above the property, so return "JsonIgnore", not "[JsonIgnore]".
The four parameters tell you which relationship you are looking at: fkTable is the table holding the foreign
key, pkTable is the one being pointed at, propName is the navigation property about to be generated, and
fkPropName is the underlying foreign key property.
Settings.ForeignKeyAnnotationsProcessing = delegate(Table fkTable, Table pkTable, string propName, string fkPropName)
{
return new[] { "System.Text.Json.Serialization.JsonIgnore" };
}; // Product
public class Product
{
public int ProductId { get; set; } // ProductId (Primary key)
public string ProductName { get; set; } // ProductName (length: 100)
public decimal UnitPrice { get; set; } // UnitPrice
public string Notes { get; set; } // Notes
public int CategoryId { get; set; } // CategoryId
public string DisplayLabel { get; private set; } // DisplayLabel (length: 150)
// Foreign keys
/// <summary>
/// Parent Category pointed by [Product].([CategoryId]) (FK_Product_Category)
/// </summary>
[System.Text.Json.Serialization.JsonIgnore]
public Category Category { get; set; } // FK_Product_Category
public Product()
{
UnitPrice = 0m;
}
}The attribute is written verbatim, which is why the fully qualified name works and needs no using. Return
"JsonIgnore" on its own and add the namespace to
Settings.AdditionalNamespaces if you prefer it short.
Breaking serialisation cycles selectively. Suppress everything except the relationships an API actually returns:
Settings.ForeignKeyAnnotationsProcessing = delegate(Table fkTable, Table pkTable, string propName, string fkPropName)
{
// Keep Order.Customer serialisable; hide everything else
if (fkTable.NameHumanCase == "Order" && propName == "Customer")
return null;
return new[] { "System.Text.Json.Serialization.JsonIgnore" };
};Validation or documentation attributes driven by the relationship rather than the column - [Required] on
a navigation property whose foreign key is non-nullable, say.
Attributes for a specific serialiser, where you are targeting several. [IgnoreDataMember] for
DataContractSerializer, [JsonIgnore] for System.Text.Json, both returned together.
Return the name without brackets. The generator adds them. Returning "[JsonIgnore]" generates
[[JsonIgnore]].
Returning null means no attributes, which is also how you say "keep this one". There is no way to say
"use the default" - there is no default. null and an empty array are the same thing.
It applies to navigation properties, not foreign key columns. To put attributes on the CategoryId
property itself, use Settings.UpdateColumn and column.Attributes.
For blanket application, the two array settings are simpler.
Settings.AdditionalReverseNavigationsDataAnnotations
and Settings.AdditionalForeignKeysDataAnnotations apply the same attributes to every reverse navigation and
every foreign key respectively, with no callback to write. Use this one when the choice varies by
relationship.
Cutting the property beats hiding it, sometimes. If a reverse navigation is never used, removing it with
Settings.ForeignKeyFilterFunc is cleaner than generating it and then
telling every serialiser to skip it.
- Settings.AdditionalReverseNavigationsDataAnnotations - the blanket version
- Settings.ForeignKeyFilterFunc - removing the property instead
- Settings.UpdateColumn - attributes on ordinary properties
- Data Annotations
- Settings Callbacks | Settings Reference
- Settings A-Z - every setting, with a page each
- Common Settings Types Explained
- Settings Callbacks
- Settings runtime values and helpers
- Filtering
- Full Control Over the Generated Code
- Enum Generation from Table Data
- Owned Entities
- JSON column support
- Global Query Filters
- Extended Property Names Feature
- Partial Properties
- File-Scoped Namespaces
- Data Annotations
- Spatial Types
- HierarchyId
- RowVersion and TimeStamp columns
- Lazy Loading
- Stored proc result sets
- Custom File-Based Templates
- Extra entities via partial classes
- INotifyPropertyChanged
- Syntax colour for T4