问题描述
我正在为用户控制器开发 Web Api 操作,但我不明白为什么在 POST 方法中出现错误:
违反了 PRIMARY KEY 约束的“PK_Section”。无法将重复键插入 dbo.Section 对象。重复键值:(3fa85f64-5717-4562-b3fc-2c963f66afa4)。
我的 IdentityUser 模型:
public string MiddleName { get; set; }
[required]
public string Surname { get; set; }
public DateTime BirthDate { get; set; }
public string Address { get; set; }
[required]
public string UserType { get; set; }
public bool ParentsAgreement { get; set; }
public Section BelongSection { get; set; }
截面模型:
[required]
public Guid Id { get; set; }
public string Name { get; set; }
public string CoachName { get; set; }
public string SportComplexTitle { get; set; }
[IgnoreDataMember]
public ICollection<User> UsersList { get; set; }
数据库上下文:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//section
modelBuilder.Entity<User>()
.HasOne(s => s.BelongSection)
.WithMany(a => a.UsersList);
modelBuilder.Entity<Section>()
.HasMany(s => s.UsersList)
.WithOne(a => a.BelongSection);
}
还有我的 POST 方法:
[HttpPost]
public async Task<ActionResult<User>> Add(User user)
{
try
{
if (user == null)
{
return BadRequest();
}
myDbContext.Users.Add(user);
await myDbContext.SaveChangesAsync();
var result = await myDbContext.Users.Include(o => o.BelongSection).FirstOrDefaultAsync(o
=> o.Id == user.Id);
return result;
}
catch (Exception)
{
throw;
}
}
所以,我收到错误,我不能在创建用户时使用现有部分的 ID。 我的 Post 方法主体是:
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6","userName": "string","normalizedUserName": "string","email": "string","normalizedEmail": "string","emailConfirmed": true,"passwordHash": "string","securityStamp": "string","concurrencyStamp": "string","phoneNumber": "string","phoneNumberConfirmed": true,"twoFactorEnabled": true,"lockoutEnd": "2021-04-15T08:31:12.271Z","lockoutEnabled": true,"accessFailedCount": 0,"name": "string","middleName": "string","surname": "string","birthDate": "2021-04-15T08:31:12.271Z","address": "string","userType": "string","parentsAgreement": true,"belongSection": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa4"
}
}
解决方法
您可以使用两种方法将现有子项添加到父项,如下所示:
_context.Section.Attach(user.BelongSection);
或者:
_context.Entry(user.BelongSection).State = EntityState.Unchanged;
务必添加 AsNoTracking()
以显示结果。
这是整个工作演示:
[HttpPost]
public async Task<ActionResult<User>> Add(User user)
{
try
{
if (user == null)
{
return BadRequest();
}
//_context.Section.Attach(user.BelongSection);
_context.Entry(user.BelongSection).State = EntityState.Unchanged;
_context.Users.Add(user);
await _context.SaveChangesAsync();
var result = await _context.Users.Include(o => o.BelongSection)
.AsNoTracking()
.FirstOrDefaultAsync(o=> o.Id == user.Id);
return result;
}
catch (Exception)
{
throw;
}
}
注意:
不确定你的asp.net core版本是什么,记得加ReferenceLoopHandling.Ignore
。
在 asp.net core 3.x 中,System.Text.Json
仅支持按值序列化,并且会引发循环引用异常。所以你需要像下面这样添加 Newtonsoft 支持:
services.AddControllers().AddNewtonsoftJson(options =>
{
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
在 .Net 5.0 中,您还可以添加 Newtonsoft 支持。此外,System.Text.Json
允许将 ReferenceHandler
设置为 Preserve
: