In this article, we’ll explore how to configure relationships between entities in Entity Framework Core (EF Core). We will use the entities Product
, Category
, Inventory
, and Supplier
. We will guide you through configuring:
- One-to-One relationships
- One-to-Many relationships
- Many-to-Many relationships with a custom join table
We’ll also apply the relationships using Attributes and Fluent API, and we’ll go step-by-step to ensure the configuration is clear.
Step-by-Step: Configuring Relationships
Step 1: Open the ProductData
Project
- Open Visual Studio.
- Navigate to the Solution Explorer and locate the
ProductData
project, where we will configure the relationships.
Step 2: Add the Supplier
Class to the ProductDomain
Project
- In ProductDomain, right-click and add a new class called
Supplier
. - Define the class as follows:
public class Supplier
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<ProductSupplier> ProductSuppliers { get; set; } // Many-to-Many relationship with Products
}
Step 3: Modify the Product
Class
- Open the
Product
class in the ProductDomain project. - Modify it to include the
ProductSuppliers
collection for the Many-to-Many relationship:
public class Product
{
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; }
[Range(0, 10000)]
public decimal Price { get; set; }
public int CategoryId { get; set; }
[ForeignKey("CategoryId")]
public Category Category { get; set; }
public Inventory Inventory { get; set; } // One-to-One relationship with Inventory
public ICollection<ProductSupplier> ProductSuppliers { get; set; } // Many-to-Many relationship with Suppliers
}
Step 4: Modify the Inventory
and Category
Classes
- In the ProductDomain project, ensure the Inventory and Category classes are correctly set up for their relationships.
Category Class:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Product> Products { get; set; } // One-to-Many relationship with Products
}
Inventory Class:
public class Inventory
{
public int Id { get; set; }
public int ProductId { get; set; }
public Product Product { get; set; } // One-to-One relationship with Product
public int Quantity { get; set; }
}
Step 5: Add the ProductSupplier
Class
- In the ProductDomain project, create a new class called
ProductSupplier
to act as the join table for the Many-to-Many relationship betweenProduct
andSupplier
:
public class ProductSupplier
{
public int Id { get; set; } // Primary key for the join table
public int ProductId { get; set; }
public Product Product { get; set; }
public int SupplierId { get; set; }
public Supplier Supplier { get; set; }
}
Step 6: Update the AppDbContext
Class in ProductData Project
- Now, open the ProductData project and modify the
AppDbContext
class to configure these relationships using Fluent API:
using Microsoft.EntityFrameworkCore;
using ProductDomain;
namespace ProductData
{
public class AppDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Inventory> Inventories { get; set; }
public DbSet<Supplier> Suppliers { get; set; }
public DbSet<ProductSupplier> ProductSuppliers { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"your-connection string ");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// One-to-One relationship between Product and Inventory
modelBuilder.Entity<Product>()
.HasOne(p => p.Inventory)
.WithOne(i => i.Product)
.HasForeignKey<Inventory>(i => i.ProductId);
// One-to-Many relationship between Category and Products
modelBuilder.Entity<Category>(entity =>
{
entity.HasKey(c => c.Id); // Set primary key
entity.Property(c => c.Name)
.IsRequired()
.HasMaxLength(50); // Limit the Name length to 50 characters
entity.HasMany(c => c.Products)
.WithOne(p => p.Category)
.HasForeignKey(p => p.CategoryId);
});
// Many-to-Many relationship between Products and Suppliers with custom join table
modelBuilder.Entity<ProductSupplier>()
.HasKey(ps => ps.Id); // Define primary key for ProductSupplier
modelBuilder.Entity<ProductSupplier>()
.HasOne(ps => ps.Product) // Configure the relationship to Product
.WithMany(p => p.ProductSuppliers)
.HasForeignKey(ps => ps.ProductId);
modelBuilder.Entity<ProductSupplier>()
.HasOne(ps => ps.Supplier) // Configure the relationship to Supplier
.WithMany(s => s.ProductSuppliers)
.HasForeignKey(ps => ps.SupplierId);
modelBuilder.Entity<ProductSupplier>()
.ToTable("ProductSuppliers"); // Define the table name
}
}
}
Step 7: Apply the Migrations
- Once all relationships are configured, open the Package Manager Console in Visual Studio:
- Go to Tools > NuGet Package Manager > Package Manager Console.
- Ensure the Default Project is set to ProductData.
- Run the following commands to create and apply the migration:
Add-Migration ConfigureRelationships
Update-Database
This will create the necessary database tables and relationships for Product
, Category
, Inventory
, Supplier
, and the ProductSuppliers
join table.
Explanation of Relationships
One-to-One Relationship (Product and Inventory):
A product can have exactly one inventory entry, and an inventory entry is linked to exactly one product. We configure this using the HasOne
and WithOne
Fluent API methods.
One-to-Many Relationship (Category and Products):
Each category can contain multiple products, while each product belongs to only one category. This is achieved using HasMany
and WithOne
methods.
Many-to-Many Relationship (Product and Supplier):
A product can have multiple suppliers, and a supplier can supply multiple products. The join table ProductSuppliers
is explicitly defined with Id
, ProductId
, and SupplierId
.
Conclusion
In this article, we walked through configuring One-to-One, One-to-Many, and Many-to-Many relationships in EF Core using our entities Product
, Category
, Inventory
, and Supplier
. We provided a step-by-step guide on how to modify the ProductData and ProductDomain projects, apply migrations, and update the database schema to reflect the relationships.
Source code EFCoreDemo
Top comments (0)