Entity Framework Core supports constructors with arguments
Keeping objects complete and valid all the time is strategy used in different methodics. It’s perhaps most popular in Domain Driven Design (DDD). Entity Framework Core 2.1 made big step forward on supporting entities that doesn’t have default empty constructor. This blog post shows how to use Entity Framework Core and entity constructors with arguments.
Using constructors with arguments
Let’s take simple Product entity that uses constructor arguments. I keep it minimal for demo purposes.
public class Product : BaseEntity
{
public int Id { get; set; }
public int TenantId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ProductCategory Category { get; internal set; }
public Product(int id, int tenantId, string name, string description, ProductCategory category)
{
Id = id;
TenantId = tenantId;
Name = name;
Description = description;
Category = category;
}
}
The code here builds with no errors. but problems begin when we try to query data from database. This line of code asks DbContext for product with id 1.
var product = _context.Products.FirstOrDefault(p => p.Id == 1);
And here’s the result.
Navigational properties are currently not supported as constructor arguments by Entity Framework Core.
We can play it around by introducing two constructors. Private one is for Entity Framework Core and public one for developers who create new instances of product.
public class Product : BaseEntity
{
public int Id { get; set; }
public int TenantId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ProductCategory Category { get; internal set; }
private Product(int id, int tenantId, string name, string description)
{
Id = id;
TenantId = tenantId;
Name = name;
Description = description;
}
public Product(int id, int tenantId, string name, string description,
ProductCategory category) : this(id, tenantId, name, description)
{
Category = category;
}
}
Notice how I made Entity Framework Core constructor as private. This way there’s no danger that developers who are writing domain entities use this constructor and forget to assign product category.
Wrapping up
By supporting contructors with arguments Entity Framework Core makes it easier to write code where entities are always valid. Although navigational properties are not supported in constructor argument list yet we were able to work it around by making special constructor for Entity Framework Core and leave classic one for developers who are working on internals of entities.
This was very helpful, thank you!
This is so much amazing content, thank you!