Home > Back-end >  Domain and persistance layer, separation of concerns with repository
Domain and persistance layer, separation of concerns with repository

Time:03-06

Domain layer

public interface IRepository<T> where T : MyEntity
{
}

public class Car : MyEntity
{
   ...   
}

public interface IMyCarRepository : IRepository<Car>
{
}

Persistance layer

public class Repository<T> : IRepository<T> where T : MyEntity
{
   public DbContext Context;
   public DbSet<T> DbSet;

   public Repository(DbContext db)
   {
      Context = context;
      DbSet = context.Set<T>();
   }
   ... Crud method implementation from the IRepository
}

public class CarRepository : Repository<Car>, ICarRepository
{
    private CarContext _db;
    public CarRepository(CarContext db) : base(context)
    {       
       _db = db;
    }
}

This works fine but as you can see CarRepository is using Car model from the Domain. Let's say that I want to change Car model in order to use MyEntityMongo I would change MyEntityMongo instead of MyEntity

public class MyEntityMongo
{
   [BsonId]
   public string Id {get; set;}
}

but this [BsonId] will bring MongoDB.Bson.Serialization.Attributes as a dependency into Domain which I don't want to do.

How would you do this without introducing Mongo library into a domain (or any other db related) The goal is to keep a clean separation of concerns between domain and persistance layer?

CodePudding user response:

I'm not a C# dev by any means, but I would consider having persistence entities be distinct from domain entities, i.e. MyEntity is a persistence representation while some other type is the domain representation of the entity.

The repository is then essentially an adapter (or perhaps even an anti-corruption layer...) between the persistence infrastructure of loading and saving persistence representations to the database and the domain logic; as an adapter it logically depends on both.

CodePudding user response:

In my view, it is better to have 2 different classes. One is for the domain logic and another one is for Persistence Model. Why? It is just my opinion, but because it is simpler and easier to refactor code in future.

The repository layer should convert persistence entities to the correct business entities and return it.

Otherwise every service will have knowledge about persistence.

Some more explanations from Sapiens Works:

  • The Domain Model models real-life problems and solutions, it models BEHAVIOR.

  • The Persistence Model models what and how data is stored, it models STORAGE STRUCTURE. See? They have pretty different purposes. The domain is the reason the application exists and everything gravitates around it. The domain should not depend on anything,especially not on a persistence IMPLEMENTATION DETAIL like EF or NH. When you design the Domain Entities, they don't know anything about persistence. Persistence, database, doesn't exist.

and a little bit more:

When you design the Persistence Layer, that layer serves the Domain and depends on it. So the persistence needs to know about the domain but not vice-versa. You design the persistence entities for storage purposes and to match the ORM's constraints (like making all the properties virtual). So you'll have Domain Entities and Persistence Entities, each with their own different purposes and implementations.

Yes, they do resemble and sometimes can be identical (when the domain is very simple) but that's nothing more than a mere coincidence. Every time you're modeling something in a repository or using an ORM , you are modelling the persistence NOT the domain. There is a reason Eric Evans recommends to start the app with the domain and to IGNORE anything db related: the Domain should not be tainted with infrastructure details, because most of the people start everything with a database centric approach. And once you start with the db, everything will evolve around it and will be constrained by it. But you don't build the application for the database, you build it for the Domain, the database is just a Persistence implementation detail.

  • Related