Closed rulrok closed 4 years ago
For now I've created my own interface (but I feel it could be part of the framework):
public interface IAclRepository<T> where T : AggregateRoot
{
AmezzeIdentityContext Context { get; }
Task SaveAsync(T aggregate);
void Save(T aggregate);
Task<T> GetByIdAsync(int id);
T GetById(int id);
}
Them I can have my aggregate as:
public class CompanyRoot : AggregateRoot
{
public CompanyRoot(int companyId)
{
CompanyId = companyId;
}
public int CompanyId { get; }
public bool Active { get; set; }
public void Activate()
{
Active = true;
AddEvent(CompanyActivated.Create(CompanyId));
}
public void Deactivate()
{
Active = false;
AddEvent(new CompanyDeactivated(CompanyId));
}
}
and I can easily work only with the IAclRepository
from my handler
public class ActivateCompanyHandler : IDomainCommandHandlerAsync<ActivateCompany>
{
private readonly IAclRepository<CompanyRoot> _repository;
public ActivateCompanyHandler(IAclRepository<CompanyRoot> repository)
{
_repository = repository;
}
public async Task<IEnumerable<IDomainEvent>> HandleAsync(ActivateCompany command)
{
var aggregate = await _repository.GetByIdAsync(command.CompanyId);
aggregate.Activate();
await _repository.SaveAsync(aggregate);
return aggregate.Events;
}
}
and for now I'm just mapping my aggregate to main entity model (manually). As the properties between my domain model and database entity increases, I'd use something like automapper or mapster. For now, it seems good enough.
public class CompanyRepository : IAclRepository<CompanyRoot>
{
public CompanyRepository(DbContext context)
{
Context = context;
}
public DbContext Context { get; }
public async Task SaveAsync(CompanyRoot aggregate)
{
var company = await Context.Companies.FindAsync(aggregate.CompanyId);
if (company == null)
return;
company.Active = aggregate.Active;
await Context.SaveChangesAsync();
}
public void Save(CompanyRoot aggregate)
{
SaveAsync(aggregate).ConfigureAwait(false);
}
public async Task<CompanyRoot> GetByIdAsync(int id)
{
var company = await Context.Companies.FindAsync(id);
if (company == null)
throw new Exception("CompanyNotFound");
return new CompanyRoot(id)
{
Active = company.Active
};
}
public CompanyRoot GetById(int id)
{
return GetByIdAsync(id).ConfigureAwait(false).GetAwaiter().GetResult();
}
}
The repositories for the write model in non event sourcing scenarios were always meant to be custom in my views but thanks for the suggestion :-)
Closing as it has not been active for a while.
I'm using
Kledex
for CQRS + DDD without event sourcing.My project has a legacy EF6 which I inject into my commands. I wanted to create an ACL to inject
IRepository<T>
and create my own implementation of it;and register it:
The problem is that this interface only works with
Guid
, but my database usesint
for primary key. I was thinking of an interface which would let me specify theTKey
In that way, I can create my own repositories for ACL and you would still keep using
IRepository
withGuid
for Kledex ES.I thought doing that because I can inject a simple
IRepository
interface only with the essential methods and make it easier to create an ACL. Also, I could make it look like the wiki example for non-ES scenario.