c# - 来自 API 控制器的数据库中的重复实体
问题描述
我有一个 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; }
}
}
WhereCandidateId
和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);
}
}
}
解决方案
推荐阅读
- azure - Azure 自定义视觉 SDK - ClientRequestError
- python - 尝试使用 kivy 制作的 buildozer 打包简单的计算器应用程序时出现错误“adb:安装失败”
- python - 如何在不使用全局变量的情况下编写重复运动函数?
- excel - excel中的数字更改为日期,解决方法导致#VALUE
- javascript - Get path of file which executed another file
- .net-core - .NET Core 项目的 GitLab CI 测试阶段失败
- debugging - 启用 gflags 时 RtlDebugCreateHeap api 中的访问冲突
- typescript - 将 IBucket 传递给 Table props 中的存储桶属性会导致缺少属性错误
- python - 在python中增加最大键大小LMDB键值数据库?
- java - 如何将平方根函数合并到我正在尝试制作的这个计算器中?