Sorry about the title, I couldn't figure out a suitable description.
I have four layers:
- Core Layer : Contains DTO's, interfaces for services and repositories.
- Business Layer : Contains "services" that handle business logic.
- Data Access Layer : Contains repositories that handle database access and conversion of entities to DTO's.
- Presentation Layer : UI stuff
I've run into an issue that I don't know how to resolve best. I am asynchronously adding an entity to the database, like so:
// The AdministrationRate has an ID property, Entity Framework does treat the property as an Identity and does increment it.
var adminRate = new AdministrationRate() {FosterChildID = fosterChild.ID};
await adminRateService.AddAdministrationRate(adminRate);
AdministrationRateService:
public async Task AddAdministrationRate(AdministrationRate administrationRate) => await repo.AddAdministrationRate(administrationRate);
AdministrationRateRepository:
//I use a generic repository to avoid code repition.
//Notice the DTO to entity conversion. ID is not set in the conversion.
public async Task AddAdministrationRate(AdministrationRate administrationRate) => await Add(administrationRate.ToEntity());
Repository:
public async Task Add(TEntity entity)
{
using (var db = new DatabaseContext())
{
db.Entry(entity).State = EntityState.Added;
await db.SaveChangesAsync();
}
}
And that does work, the problem is that after it has been added the newly generated id of the entity has not been reflected in the DTO (DTO.ID = 0).
I can't possibly return the updated entity because it would require me to convert the entity to a DTO in my presentation layer to keep it async all the way.
I also can't return just the ID because of the generic repository.
I really don't want to get rid of the generic repository as it is quite useful, but I can't really see another way to do it securely without altering the database (which I can't do).
So, what do I do?
Answer: I found two solutions to this issue, the latter being the one I'm actually going with.
Solution 1:
I figured out that I could make the Add method return the ID of an entity, by marking the Add method of the generic repository virtual, then overriding it in one of the specific repositories and finally catch the result from the calling code. This would of course mean more code, but also that I would not be converting from entities to DTO's in the wrong layer (Not that that was an option).
Solution 2:
Apparently the
await
keyword returns the result type of a task asynchronously, instead of blocking it likeresult
, so I was able to convert and return a DTO from my repository:AdministrationRateRepository:
I would like if someone could comment wether I need to make my
ToEntity()
andToModel()
methods async, and how that would be done.EDIT: Oh, didn't notice someone had posted. I'll have a look at your suggestions Akos, thanks.