References and collections
The model of an application is usually divided into several entities representing the data structure of the application. These entities often have relationships with each other.
In Neos, there are two ways to represent the relationship between two entities : references and collections.
A relationship can be configured on either of the involved entities. Whether you need to create a reference or a collection depends on the entity you are editing and the type of their relationship.
References
When an A
entity depends on one instance of a B
entity, then we can configure a reference on the A
entity. This type of relationship is also referred to as one-to-one or many-to-one depending whether the referenced entity (B
) can be referenced by only one or multiple instances of the A
entity.
Examples of references that an Person
entity (A
) can have with other entities (B
) :
In Neos Studio, configuring a reference on an entity is done in two steps.
[optional] Creating scalar properties to store the reference data
Note
If you do not perform this step, the scalar property will be automatically generated from the information entered in the reference (next step).
This step is to add one or several scalar properties on the A
entity that will store the key that uniquely identifies the referenced entity (B
).
In the case of the relationship between Person
and Address
, the auto-incremented integer ID
property is the key that uniquely identifies each Person
and Address
. Therefore, to be able to reference an Address
on a Person
, we will need to add an integer AddressID
property on the Person
entity.
Had the key of the Address
entity been composed of multiple properties, we would need to create the same amount of scalar properties on the Person
entity to be able to reference an Address
.
Configuring the reference with one-to-one relationship
This step is to configure the reference on the A
entity. In Neos Studio, on the entity, use the button Add reference (one to one)
to add it. Here we need to specify the referenced entity (B
).
For the relationship between Person
and Address
, we will create an new reference on the Person
entity and reference the Address
entity.
After that, a navigation property must be configured by setting its name and mapping the scalar properties to store the reference data on the A
entity. If the scalar properties were not created manually in the previous step, they will be automatically added when saving the reference. This navigation property will allow the access to the properties of the referenced entity (B
) instance of an A
entity instance.
In the case of the relationship between Person
and Address
, we can name the navigation property Address
and map the AddressID
property of the Person
entity to Address.ID
.
After generating the application, it will be possible to access the Street
property of the Address
of a Person
using the following C# code.
string street = employee.Address.Street;
Warning
Due to performance concerns, data accessible through navigation properties is loaded by default. See article about EF Core Lazy loading.
Note
When the Address
navigation property is loaded, both employee.AddressID
and employee.Address.ID
properties return the same value.
[optional] Configuring a collection navigation property on the referenced entity
In the case of many-to-one relations, it is possible to configure a collection that will automatically be generated on the referenced entity (B
).
For example, when configuring the reference to a Company
on a Person
, we can create the collection in the entity Company
with the name Employees
. This will automatically generate a collection named Employees
on the Company
entity.
This collection will allow the access to the data of all the Persons
that are employed by a Company
using the following C# code.
string name = company.Employees.First().Name.
Note
The configuration of a collection on a reference is optional. If not done, the only drawback is that it will not be possible to access to the A
entity from the referenced B
one. For example, it will not be possible to access to the Employees
from a Company
entity, but accessing to a Company
from a Person
it employs will work just fine.
Collections (one-to-many relationship)
We saw that when configuring a one-to-many relationship on an entity , a reference can be created on the A
entity.
In Neos Studio, on the entity, use the Add reference (one to many)
button to add it.But the relationship can also be configured from the B
entity perspective. In this case, the relationship is viewed from a one-to-many point of view. Therefore, instead of configuring a reference on the A
entity, we can choose to configure a collection on the B
entity .
Example of the relationship between a Person
(A
) and a Company
(B
) from the Company
perspective :
Creating a collection on the "one side" of a relationship (B
) is equivalent to creating a reference with a **collection_ on the "many side" of the relationship (A
). Therefore, the creation of a collection requires similar steps to the creation of a **reference__.
Creating scalar properties to store reference data on the "many side" entity
When a collection is created on a B
entity, a reference will automatically be generated on the A
entity. Therefore we need to create scalar properties on the A
entity to store the reference data to the B
entity as described previously.
In the case of the relationship between Company
and Person
, we will need to add an integer CompanyID
property on the Person
entity.
Once again, had the key of the Company
entity been composed of multiple properties, we would need to create the same amount of scalar properties on the Person
entity.
Configuring the collection
The second step is to create the collection on the B
entity. This is done with the Add collection
button. Here we need to specify the referenced entity (A
) that it will be linked to.
For the relationship between Company
and Person
, we will create an new collection on the Company
entity and reference the Person
entity.
After that, a navigation property must be configured by setting its name. This navigation property will allow the access to all the A
entity instances that reference a B
entity instance.
In the case of the relationship between Company
and Person
, we can name the navigation property Employees
.
After generating the application, it will be possible to access the Name
property of one of the Employees
of a Company
using the following C# code.
string name = company.Employees.First().Name.
Warning
Due to performance concerns, data accessible through navigation properties is loaded by default. See article about EF Core Lazy loading.
Finally, we need to configure the reference that will automatically be generated on the referenced entity (A
). First we must set its name, then we need to map the properties linked to the scalar properties of the referenced entity (A
) that were created earlier to store the reference data. This navigation property will allow the access to the properties of the referenced entity (B
) instance of an A
entity instance.
For our example, we can call this reference Company
and map the scalar property CompanyID
.
After generating the application, it will be possible to access the Name
property of one of the Company
employing a Person
using the following C# code.
string name = person.Company.Name.
Note
When the Company
navigation property is loaded, both person.CompanyID
and person.Company.ID
properties return the same value.