So I have built a domain model and some logic into that. I have created two repositories for two aggregate roots.
My question is how to access to the reference data from these layers?. For example, say we have the following types Elder
and Young
.
Our application entry points expect Elder
or Young
as inputs. But, to validate and save this in the database (which has a foreign key to another table PERSON_TYPE
which has these 2 values), I need to convert these IDs to store aggregate roots.
Could I create a PersonTypeRepository
(in the domain layer) and use it when I persist my aggregate roots? Should this conversion happen in domain layer or should it happen in the application layer? For example, from a service
Edit: For now I have gone with this approach. From controller
I call Assembler
for the DTO
. I created a non-domain model repository (Infrastructure layer). Then from Assembler
I build the domain model (caveat is exposing setMethods()
of a domain model) using the Autowired
Repository
-
@Laiv can you please explain?Dexters– Dexters03/26/2019 04:49:55Commented Mar 26, 2019 at 4:49
-
Why design an entry point that accepts one of two values? Does the caller to your entry point not know which type is being passed? "Garbage in, garbage out."user3347715– user334771505/05/2020 15:19:19Commented May 5, 2020 at 15:19
1 Answer 1
If you have three seperate tables, then creating three Domain Models(Entity Model) and repositories is common way. Then, manage business and transaction scope on Service Layer(Application Layer).
If it looks hard to create individual repository for each table, then you can use Generic Repository Pattern. This generic repository lets you use common method for each Domain Model.
Note : You can also use Unit of Work instead of using these 3 separate repositories but it is not shown from here.
public interface IGenericRepository<T> where T : class
{
T Get(int id);
int Create(T model);
int Update(T model);
void Delete(T model);
List<T> GetAll();
}
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private readonly IDbContext _dbContext;
public GenericRepository(IDbContext dbContext)
{
_dbContext = dbContext;
}
// implementations
}
public class SomeService
{
private readonly IGenericRepository<Young> _youngRepository;
private readonly IGenericRepository<Elder> _elderRepository;
private readonly IGenericRepository<PersonType> _personTypeRepository;
public SomeService(IGenericRepository<Young> youngRepository,
IGenericRepository<Elder> elderRepository,
IGenericRepository<PersonType> personTypeRepository)
{
_youngRepository = youngRepository;
_elderRepository = elderRepository;
_personTypeRepository = personTypeRepository;
}
// this method parameters can be changed and this personTypeId
// can be into elder or young instance.
public void SomeMethod(Elder elder, Young young, int personTypeId)
{
PersonType personType = _personTypeRepository.Get(personTypeId);
// some validations here.
// your business requirements
try
{
// using(begin transaction here by your dbcontext)
// getting dbconext can change by your design.
_youngRepository.Create(young);
_elderRepository.Update(elder);
// commit transaction.
}
catch (Exception ex)
{
// rollback here
throw ex;
}
}
}