【发布时间】:2023-01-28 06:44:53
【问题描述】:
在 ASP.NET Core-6 Web API 实体框架中,我希望应用程序同时对数据库中的同一模型执行更新和插入。
我有这段代码:
public async Task<Response<string>> CreateIdentiticationAsync(CreateIdentiticationDto model)
{
var response = new Response<string>();
using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
try
{
var identification = _mapper.Map<Identification>(model);
var existingIdentifications = await _dbContext.Identifications.Where(e => e.IsModified == false).ToListAsync();
foreach (var existingIdentification in existingIdentifications)
{
if (existingIdentification != null)
{
existingIdentification.IsModified = true;
_unitOfWork.UserIdentifications.Update(identification);
await _unitOfWork.Save();
}
}
Identification.IsModified = false;
Identification.Type = model.Type;
Identification.Name = model.Name;
await _unitOfWork.UserIdentifications.InsertAsync(identification);
await _unitOfWork.Save();
response.StatusCode = (int)HttpStatusCode.Created;
response.Successful = true;
response.Message = "Created Successfully!";
transaction.Complete();
return response;
}
catch (Exception ex)
{
transaction.Dispose();
response.Message = "An error occured";
response.Successful = false;
response.StatusCode = (int)HttpStatusCode.BadRequest;
return response;
}
}
}
当用户想要插入一条新记录时,我希望应用程序首先检查模型,如果不存在记录,它应该只插入新记录。
但如果它存在,它应该将所有 IsModified 更新为 true,然后继续并插入一条新记录。
但是,当不存在记录时,我可以插入新记录。 但是我遇到的问题是,当它想要更新和插入新记录时,出现了这个错误:
违反 PRIMARY KEY 约束“PK_identifications”。无法在对象“dbo.identifications”中插入重复键。重复键值为 (81fe9b8d-2d9c-4d49-8f92-22afe043e327)。
注意:ID 是 Guid 并且是自动生成的
我该如何解决这个问题?
谢谢
【问题讨论】:
-
DbContext 不需要 TransactionScope 或“UnitOfWork”——它已经是一个工作单元。它跟踪所有变化并持续存在全部当调用
SaveChanges时,它们在数据库事务中。在循环中调用Save()要么什么都不做,要么破坏工作单元功能。我怀疑这就是您在顶部添加TransactionScope的原因。这只是掩盖了问题 -
什么是
_unitOfWork,它的Save方法有什么作用?除非它是空操作,否则它只会导致问题。Identifications是如何定义的?什么是主键,它是如何设置的?如果它是数据库生成的,则不会有重复项。如果按预期使用 EF Core,则也不会有重复项,即使您尝试两次附加相同的分离对象也是如此。仅当两个不同的对象具有相同的 PK 值时才会出现该错误 -
这段代码有什么作用?似乎有一个部分更新了
identification对象 N 次,每个存储的未修改对象都有一个。另一个是插入同一个identification已经更新了 N 次了。还有一个是修改不相关的Identification对象但从不存储它。如果你想存储identification对象,你只需要两行,_context. Update(identification); _context.SaveChanges();