I have two .NET Core entities; UserAccount and Customer that has UserAccountId as foreign key. I want to have a one generic method that first creates UserAccount. Then I take UserAccountId from it and then save it in Customer entity. All in one request. Also I have generic Create method. All this would be trivial to me if it weren't for these generics and inheriting everywhere I go: Controllers, Services, overriding... so this is a setup:
Generic BaseCRUDService: (T is for Models, TDb is for DatabaseModels, TCreate is for Request model I'm sending through controllers)
public class BaseCRUDService<T, TDb, TSearch, TCreate, TUpdate>
: BaseService<T, TDb, TSearch>
where TDb : class where T : class
where TSearch : BaseSearchObject
{
public BaseCRUDService(DataDbContext context, IMapper mapper)
: base(context, mapper)
{}
public virtual async Task PrepareBeforeCreate(TDb db, TCreate create)
{}
public virtual async Task<T> Create(TCreate create)
{
var set = context.Set<TDb>();
var entity = mapper.Map<TDb>(create);
set.Add(entity);
await PrepareBeforeCreate(entity, create);
await context.SaveChangesAsync();
return mapper.Map<T>(entity);
}
}
This is an implemenation of UserAccountService:
public class UserAccountService
: BaseCRUDService<Models.UserAccount, Database.UserAccount, UserAccountSearchObject, UserAccountCreateRequest, UserAccountUpdateRequest>, IUserAccountService
{
public UserAccountService(DataDbContext context, IMapper mapper)
: base(context, mapper)
{}
public override async Task PrepareBeforeCreate(Database.UserAccount entity, UserAccountCreateRequest create)
{
entity.PasswordSalt = GenerateSalt();
entity.PasswordHash = GenerateHash(entity.PasswordSalt, create.Password);
}
}
When I hit CustomerService Create method (which by the way is the same as UserAccountService, inherits BaseCRUDService also and uses the same Create method), I need to call Create Method that will first create UserAccount and then I'll set that UserAccountId to the Customer.
I tried calling userAcountService.Create(create) in CustomerService method PrepareBeforeCreate like this:
public override async Task PrepareBeforeCreate(Database.Customer entity, CustomerCreateRequest create)
{
var userAccountEntity = userAccountService.Create(create as UserAccountCreateRequest);
entity.UserAccountId = userAccountEntity.Id;
}
but what I eventually get and I kinda get it is this error:
A second operation was started on this context before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext.
So, my question is basically this: is there anyway I could modify this generic method or add to it to insert two models on one request? Thanks.