Дублированные объекты в базе данных от контроллера API - PullRequest
0 голосов
/ 17 июня 2019

У меня есть модель EF Core, определенная как:

namespace TestApp.DataAccess.Models {
    public class Candidate
    {
        public int CandidateId { get; set; }
        public Guid UniqueKey { get; set; }
        public string Name { get; set; }
        public virtual List<Job> Jobs { get; set; }
    }

    public class Job
    {
        public int JobId { get; set; }
        public Guid UniqueKey { get; set; }

        public int CandidateId { get; set; }
        public virtual Candidate Candidate { get; set; }

        public string Title { get; set; }
    }
}

Где CandidateId и JobId - первичные ключи.

Обе сущности также имеют свойство UniqueKey, которое является Guid. Это генерируется нашим клиентом и публикуется в нашем API в теле запроса. Мы никогда не должны иметь более одного Job с одним и тем же свойством UniqueKey.

В идеале это должно обеспечиваться базой данных с уникальным ограничением, но в настоящее время этого нет.

Вместо этого в нашем контроллере мы проверяем, существует ли UniqueKey. Если этого не произойдет, мы создадим новый Job. Если это так, то мы обновляем существующую запись:

foreach (var jobModel in model.Jobs) {
    //Check if the job already exists for the entity
    var jobEntity = candidate.Jobs.FirstOrDefault(x => x.UniqueKey == jobModel.UniqueKey);

    //If not, then create it
    if (jobEntity == null) {
        jobEntity = new Job { UniqueKey = jobModel.UniqueKey };
        candidate.Jobs.Add(jobEntity);
    }

    jobEntity.Title = jobModel.Title;
    //...
}

Недавно я начал видеть дубликаты Jobs:

JobId         CandidateId         Title         UniqueKey
201           100                 Teacher       4177b6da-7a4c-4032-b13d-8e3e2d2aeaca
202           100                 Teacher       4177b6da-7a4c-4032-b13d-8e3e2d2aeaca

Это не то, что я считал возможным с помощью приведенного выше кода. Прежде чем применить уникальное ограничение к базовой базе данных SQL, я пытаюсь понять, как это происходит, чтобы убедиться, что я не просто навязываю более значительную проблему.

Что может вызвать создание этих двух записей? Может быть, это связано с тем, что дублированные запросы одновременно попадают на нашу конечную точку API?

Это полный пример кода:

namespace TestApp.DataAccess.Models {
    public class Candidate
    {
        public int CandidateId { get; set; }
        public Guid UniqueKey { get; set; }
        public string Name { get; set; }
        public virtual List<Job> Jobs { get; set; }
    }

    public class Job
    {
        public int JobId { get; set; }
        public Guid UniqueKey { get; set; }

        public int CandidateId { get; set; }
        public virtual Candidate Candidate { get; set; }

        public string Title { get; set; }
    }
}

namespace TestApp.Api.Controllers {
    [Route("api/[controller]")]
    public class CandidateController : BaseController {
        public ServerApplicationContext _context { get; set; }

        public CandidateController(ServerApplicationContext context) {
            _context = context;
        }

        public async Task<Candidate> findEntityOrDefault(Guid key) {

            if(entity == null) {
                return null;
            }


        }
        [HttpPost]
        public async Task<IActionResult> Post([FromBody]CandidateViewModel model) {

            //Load the existing entity
            var candidate = await _context.Candidates.FirstOrDefaultAsync(x => x.UniqueKey == key);

            //If we don't find a candidate then create one
            if(entity == null) {
                //...
                //candidate = new Candidate { ... }
                //...

            } else {
                //Else load in child properties for the existing candidate

                candidate.Jobs = await _context.Jobs.Where(x => x.CandidateId == entity.CandidateId).ToListAsync();

                return entity;
            }

            //Add jobs from the model to our entity
            foreach (var jobModel in model.Jobs) {
                //Check if the job already exists for the entity
                var jobEntity = candidate.Jobs.FirstOrDefault(x => x.UniqueKey == jobModel.UniqueKey);

                //If not, then create it
                if (jobEntity == null) {
                    jobEntity = new Job { UniqueKey = jobModel.UniqueKey };
                    candidate.Jobs.Add(jobEntity);
                }

                jobEntity.Title = jobModel.Title;
                //...
            }


            //Add or update the candidate to the DB
            if (candidate.CandidateId == 0)
                _context.Add(candidate);
            else
                _context.Update(candidate);

            //Commit changes
            await _context.SaveChangesAsync();

            var viewModel = Mapper.Map<CandidateViewModel>(candidate);
            return new ObjectResult(viewModel);
        }        
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...