/// <inheritdoc /> protected override async Task Handle(SyncTvMazeDbCommand request, CancellationToken cancellationToken) { var tvMazeShows = await GetNextPageShowsAsync(); while (tvMazeShows.Any()) { foreach (var tvMazeShow in tvMazeShows) { // Perharps another thread (or instance of service) has already added the row with same ID var showEntity = await _showsRepository.GetShowAsync(tvMazeShow.ID); if (showEntity == null) { showEntity = new Show(tvMazeShow.ID, tvMazeShow.Name); // Use eventual consistency and idempotent inserts instead of UoW. // Firstly insert all the cast of the show, and only then that show. // Even if the job fails it will start again and repeat the previous operation. var tvMazeCasts = await _tvMazeService.GetShowCastsAsync(tvMazeShow.ID); foreach (var tvMazeCast in tvMazeCasts) { if (tvMazeCast.Person != null) { var personEntity = new Person(tvMazeCast.Person.ID, tvMazeCast.Person.Name, String.IsNullOrEmpty(tvMazeCast.Person.Birthday) ? (DateTime?)null : DateTime.Parse(tvMazeCast.Person.Birthday)); personEntity = await _personsRepository.InsertIfNotExistsAsync(personEntity); showEntity.AddCast(personEntity); } } await _showsRepository.InsertIfNotExistsAsync(showEntity); } } tvMazeShows = await GetNextPageShowsAsync(); } }