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

假如想象 提交于 2021-01-29 16:44:56

问题


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?


回答1:


As requested here's a little more details for my opinion stated in the comments.


The main reason why I think your current approach is a bad idea is that it violates the separation of concerns design principle: when you are mixing domain models with data access models, you make your domain logic completely dependent on how you model the data in your database. This quickly limits your options because the database may have some restrictions on how you can model your data that doesn't fit well with the domain logic you want to implement as well as making maintenance difficult. E.g. if you decide to split up one DB table into two then you might have a big task ahead of you in order to make your domain logic work with those two new models/tables. Additionally, making performance optimizations in your database easily becomes a nightmare if not thought through ahead of time - and you shouldn't spend time thinking of optimizing your system before it's necessary.

I know this is a little abstract since I don't know much about your domain but I'm sure I could find more arguments against it.


Instead, separating data access models (and in general all external data models) from your domain models makes it much easier to maintain: if you need to make some changes to your database, you simply need to update the logic that maps the data from your data access models to your domain model - nothing in your domain logic needs to change.

In the examples you have given, you have already logically separated your domain models and data access models into two separate projects. So why not follow through with that thought and separate the two with a binding/mapping layer in-between?




回答2:


Is it possible to configure the EF so that it allows us to use this concept?

Yes. Essentially you have DTO's, and your Entities derive from your DTOs. So when you fetch an Entity you can return it directly. But if you wouldn't be able to attach a non-Entity, so you'd have to map it. It's going to be inconvenient, and like 99.999% of bespoke entity and repository designs, will be ultimately a waste of time.

This is somewhat similar to the what EF already does for you. Start with persistence-ignorant Entity classes, and introduce persistence-aware runtime subtypes for scenarios that require them, which is basically just Lazy Loading.



来源:https://stackoverflow.com/questions/62229071/it-is-possible-to-use-child-class-to-implement-separation-of-concerns-using-ef-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!