Search K
Appearance
Relationships are defined as fields. One-to-one, one-to-many and many-to-many relationships can be defined with BelongsTo
and HasMany
fields.
Relationship navigations from EF Core are used to load related entities. Consequently, relationships without any navigation are not supported. Unidirectional relationship support is limited to its outgoing side.
1 The join table needs a separate primary key to show additional data or relationships. We recommend the Many-to-many and join table with separate primary key relationship to show additional data or relationships.
2 To achieve the symmetry the relationship has to be added from both sides manually.
To configure a relationship in Centias only its cardinality is relevant. The following sections provide examples for the three cardinalities.
All examples are assuming a bidirectional relationship, where all involved entities have a navigation to their associated entities. If the relationship is unidirectional, it can only be displayed by the outgoing entity. For example in a relationship A->B only A can display its relationship to B.
A one-to-one relationship is used to model situations where one entity can be associated only one instances of another entity. For example, in a database, an order have a related invoice and an invoice has one order.
In this example, an order can have an invoice and an invoice must have an order.
Our example model class Order
contains the property Invoice
, which describes one side of the one-to-one relationship.
public class Order {
[Key]
public int Id { get; set; }
public Invoice? Invoice { get; set; }
}
Our Invoice
model class in return contains the property Order
with the OrderId
as foreign key, which determines the other side of the one-to-one relationship.
public class Invoice {
[Key]
public int Id { get; set; }
[Required]
public Order Order { get; set; }
public int OrderId { get; set; }
}
In our order resource the one-to-one relationship with invoice entities is defined with BelongsTo<TEntitiy, TRelated>
. To check your setup see if the following statement holds:
A
TEntity
belongs toTRelated
.
public class OrderResource : Resource<Order, ApplicationDbContext, int>
{
public OrderResource(ApplicationDbContext context): base(context) {}
public override IList<IResoureFieldBuilder> Fields()
{
return
[
BelongsTo.Make<Order, Invoice>("Invoice", nameof(Order.Invoice))
];
}
}
As a result each order contains a reference to its related invoice.
In the invoice resource the relationship to an order is defined with BelongsTo<TEntitiy, TRelated>
. You can verify your setup with the following statement:
TEntity
belongs toTRelated
.
public class InvoiceResource : Resource<Employee, ApplicationDbContext, int>
{
public EmployeeResource(ApplicationDbContext context): base(context) {}
public override IList<IResoureFieldBuilder> Fields()
{
return
[
BelongsTo<Invoice, Order>.Make("Order", nameof(Invoice.Order))
];
}
}
As a result each invoice contains a reference to its related order.
A one-to-many relationship is used to model situations where one entity can be associated with multiple instances of another entity. For example, in a database, a team may have many employees, but each employee is associated with only one team.
In our example, an employee is part of one team and one team can have many employees.
Our example model class Employee
contains a property Team
to indicate which team an employee is a member of.
public class Employee
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public Team Team { get; set; }
}
A Team
has a property Members
, which contains a list of employees.
public class Team
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public ICollection<Employee> Members { get; set; } = [];
}
In our team resource the one-to-many relationship with employee entities is defined with a HasMany<TEntitiy, TRelated>
field. Your setup is correct if the following statement holds:
A
TEntity
has manyTRelated
.
public class TeamResource : Resource<Team, CompanyContext, int>
{
public TeamResource(CompanyContext context) : base(context) {}
public override IList<IResoureFieldBuilder> Fields()
{
return
[
TextField.Make("Name", nameof(Team.Name)).AsDisplayName(),
HasMany<Team, Employee>.Make("Members", nameof(Team.Members))
];
}
}
As a result, each team contains a list of associated employees.
In the employee resource the relationship to a team is defined with a BelongsTo<TEntitiy, TRelated>
field. You can verify your setup with the following statement:
TEntity
belongs toTRelated
.
public class EmployeeResource : Resource<Employee, CompanyContext, int>
{
public EmployeeResource(CompanyContext context) : base(context) {}
public override IList<IResoureFieldBuilder> Fields()
{
return
[
TextField.Make("Name", nameof(Employee.Name)),
BelongsTo<Employee, Team>.Make("Team", nameof(Employee.Team))
];
}
}
Now each Employee
contains a reference to the associated Team
.
A many-to-many relationship is used to model situations where multiple entities can be associated with multiple instances of another entity. For example, in a database, a product may be included in multiple product bundles, and a product bundle may include multiple products.
In this example, a product can be contained in multiple product bundles and one product bundle can include many products.
Our example model class Product
contains the property Bundles
, which describes one side of the many-to-many relationship.
public class Product
{
[Key]
public int Id { get; set; }
public ICollection<ProductBundles> Bundles { get; set; } = [];
}
Our ProductBundle
model class in return contains the property Products
, which determines the other side of the many-to-many relationship.
public class ProductBundle
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public ICollection<Product> Products { get; set; } = [];
}
In our product resource we define the many-to-many relationship through a HasMany<TEntity, TRelated>
field. To check our relationship setup, see if the following statement holds:
A
TEntity
has manyTRelated
.
public class ProductResource : Resource<Product, ApplicationDbContext, int>
{
public ProductResource(ApplicationDbContext context) : base(context) {}
public override IList<IResoureFieldBuilder> Fields()
{
return
[
HasMany<Product, ProductBundle>.Make("Bundles", nameof(Product.Bundles)),
];
}
}
With this configuration, each product bundle contains a list of its associated products.
In our product bundle resource the relationship to products is defined with a HasMany<TEntitiy, TRelated>
field. You can verify your setup with the following statement:
TEntity
has manyTRelated
.
public class ProductBundleResource : Resource<ProductBundle, ApplicationDbContext, int>
{
public ProductBundleResource(ApplicationDbContext context) : base(context) {}
public override IList<IResoureFieldBuilder> Fields()
{
return
[
HasMany<ProductBundle, Product>.Make("Products", nameof(ProductBundle.Products))
];
}
}
As a result, each product bundle displays its associated products.