Relations
Relations are used to link entities. This page discusses how to access relations, their value(s) and how to modify these values.
Relation types
M features four main relation types:
IChildToOneParentRelation
IChildToManyParentsRelation
IParentToOneChildRelation
IParentToManyChildrenRelation
These are the most strongly typed interfaces and are recommended to be used most of the time. However, they also derive from the following interfaces (where appropriate):
IChildRelation
IParentRelation
IToOneRelation
IToManyRelation
IRelation
These interfaces can be used for polymorphism or quickly working with relations if the type is not specified exactly.
The type of the relation depends on the cardinality of the relation definition, and the role of which side of the relation wanted.
Getting relations
Relations can be retrieved from an entity.
Property names are not case sensitive.
Non-generic
To get a relation without specifying the type:
IRelation relation = entity.GetRelation("AssetTypeToAsset");
Generic
To get a typed relation (preferred approach):
IChildToManyParentsRelation relation = entity.GetRelation<IChildToManyParentsRelation>("AssetTypeToAsset");
When the relation is not found or is not loaded, null
will be returned. However, relations can be lazy loaded. See lazy loading for more information.
All loaded relations can also be accessed using the IEntity.Relations
property. This is useful for e.g. filtering relations with LINQ.
Relation values
Depending on the relation interface you are using, there are different ways to get and set values. For a complete overview, see the API docs.
Non-generic
IRelation
supports a few operations on values. While this might be the easiest way to work with relations, it is also more error prone. It is advised to use the four main relation interfaces and use their properties.
Getting the values will always return a list of ids. If the relation is a IToManyRelation
, the list can contain zero to many values. If the relation is a IToOneRelation
it will either return an empty list or exactly one value.
IList<long> values = relation.GetIds();
Setting values is done by passing a collection of ids. If the relation is a IToManyRelation
, the list can contain zero to many values. If the relation is a IToOneRelation
, the list can contain zero or exactly one value.
relation.SetIds(ids);
To clear a relation's value(s):
relation.Clear();
Generic
The strongly typed relations have better support for values. Take for example the IParentToManyChildrenRelation
.
To get its children:
IList<long> children = parentToManyChildrenRelation.Children;
To add a child:
parentToManyChildrenRelation.Children.Add(id);
Another useful example is the IToManyRelation
. Since the .NET IList
does not support adding multiple items at once, the IToManyRelation
adds this feature:
toManyRelation.AddRange(ids);
Dealing with self-referencing relations
Self-referencing relations are relations that point to the same entity definition on both sides of the relation. This results in two relation objects with the same name on the entity.
When you get a relation in a non-generic way, you will need to specify the role you want. If you don't, an InvalidOperationException
will be thrown, since there are two matching relations.
IRelation relation = entity.GetRelation("SelfReferencingRelation", RelationRole.Child);
When you get the relation in a generic way, the SDK extract the role from the interface. So the following example will work for normal and self-referencing relations:
IChildToManyParentsRelation relation = entity.GetRelation<IChildToManyParentsRelation>("SelfReferencingRelation");
This will extract the role Child
internally.
Do not pass IRelation
to the generic GetRelation
or the SDK will not be able to extract the role.