samedi 6 juin 2020

It is possible to use child class to implement Separation of concerns using EF Core?

My goal is async loading of related entities using DBContext.

Let imagine two projects. The first named MyApp.Domain and contains domain entities.

namespace MyApp.Domain
{
    public class PlanPage
    {
        public Guid Id { get; set; }
    }
}
namespace MyApp.Domain
{
    public class PlanPageDay
    {
        public Guid Id { get; set; }
        public Guid PlanPageId { get; set; }
    }
}

The second project named MyApp.Infrastructure.EntityFramework and contains configuration of projection entities to database. It also contains class which extends domain entity and implements Entity framework specific logic.

namespace MyApp.Infrastructure.EntityFramework.Models
{
    public class PlanPageEntity : PlanPage
    {
        private readonly ApplicationDbContext _applicationDbContext;

        protected PlanPageEntity(ApplicationDbContext applicationDbContext)
        {
            _applicationDbContext = applicationDbContext;
        }

        public ICollection<PlanPageDay>? Days { get; set; }

        public async Task<ICollection<PlanPageDay>> GetDays()
        {
            return Days ??= await _applicationDbContext.PlanPageDays
                .Where(pd => pd.PlanPageId == Id)
                .ToListAsync();
        }
    }
}

The purpose of this example is simple. We separate infrastructure code from domain code. Look how do we plan to use this concept:

// Entity initializing code. Placing somewhere in domain logic.
var plan = new PlanPage(/*some constructor arguments*/);

// Entity loading code. Placing somewhere in infrastructure implementation.
public async Task<PlanPage> GetPlanPage(Guid id)
{
    return await _applicationDbContext.Set<PlanPageEntity>().FindAsync(id);
}

Note that we tell to Entity framework to use child class (PlanPageEntity) so it can handle all specific things that it can.

The question is: Is it possible to configure the EF so that it allows us to use this concept?

Aucun commentaire:

Enregistrer un commentaire