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.

Entity Framework Core: Exception for navigational property in constructor argument list

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.

Liked this post? Empower your friends by sharing it!

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    Leave a Reply

    Your email address will not be published. Required fields are marked *