无法在实体框架核心 6 上插入具有导航属性的数据



帖子更新解决方案

假设我有两个简单的模型类来解释我的问题。每个模型作为DB关系的导航属性。迁移、创建和更新数据库以及GET端点的邮差都没问题。这个问题……我可以POST一个用户,但不能POST一个汽车记录。我用Fluent API方法遵循微软教程中的代码第一,但我也尝试了数据注释,但结果相同(在其他一些测试之间,我也尝试了"虚拟"关键字)。一个简短的搜索指向我嵌套的对象/数组在做POST记录到DB,但也没有成功,同样的错误!这是一个小的例子,从我的项目超过6个模型类,但有了这两个我想我可以解释我的问题。这是一对多关系。

public class User
{
public int Id { get; set; }
public string Age { get; set; }
public string Name { get; set; }
public string City { get; set; }
public string Country { get; set; }
// navigation property
public List<Car> Cars { get; set; }
}

And Car model:

public class Car
{
public int Id { get; set; }
public int Year { get; set; }
public string Plate { get; set; }
// navigation property
public int UserId { get; set; }
public User User { get; set; }
}

这里是DbContext:

public MyPersonalProjectContext(DbContextOptions<MyPersonalProjectContext> options) : base(options)
{
}
public DbSet<User> Users { get; set; }
public DbSet<Car> Cars { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// setting database relationships with constraints and cascade delete
// one-to-many for User -> Car tables
modelBuilder.Entity<Car>()
.HasOne(u => u.User)
.WithMany(c => c.Cars)
.HasForeignKey(u => u.UserId)
.HasConstraintName("FK_User_Cars")
.OnDelete(DeleteBehavior.Cascade);
}

I POST这个例子记录在api/cars端点:

{
"year": 2012,
"plate": "YY-11-BB",
"userId": 2
}

邮差给我:

{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-36feeb71fcd60b67da499091bf94598a-1b14d3e2c48fc635-00",
"errors": {
"User": [
"The User field is required."
]
}
}

我也试过张贴一个空数组来尝试作弊:

{
"year": 2012,
"plate": "YY-11-BB",
"userId": 2,
"user": []
}

CarsController:

public async Task<ActionResult<Car>> PostCar(Car car)
{
if (_context.Cars == null)
{
return Problem("Entity set 'MyPersonalProjectContext.Cars'  is null.");
}
_context.Cars.Add(car);
await _context.SaveChangesAsync();
return CreatedAtAction("GetCar", new { id = car.Id }, car);
}

(解决方案):经过一番挖掘和尝试,我找到了解决方案,至少对我来说是这样。我将在这里张贴我所取得的成就,以便许多有同样问题的人也可以解决它!

创建一个ModelDTO(对于那些不知道什么是DTO的人,这里有一个很好的解释,来自这个12年前的主题什么是数据传输对象(DTO)?)

public class CreateCarDTO
{
public int Id { get; set; }
public int Year { get; set; }
public string Plate { get; set; }
public int UserId { get; set; }
}

然后我在我的控制器POST方法做了一些改变:

[HttpPost]
public async Task<ActionResult<Car>> PostCar(CreateCarDTO request)
{
var user = await _context.Users.FindAsync(request.UserId);
if (user == null)
{
return NotFound();
}
var newCar = new Car
{
Year = request.Year,
Plate = request.Plate,
User = user
};
_context.Cars.Add(newCar);
await _context.SaveChangesAsync();
return await GetCar(newCar.UserId);
}

最后对于JSON异常,我在Model:

中添加了[JsonIgnore]
public class Car
{
public int Id { get; set; }
public int Year { get; set; }
public string Plate { get; set; }
// navigation property for parent entity and foreign key
// one-to-many car -> user
public int UserId { get; set; }
[JsonIgnore]
public User User { get; set; }
}

希望这个解决方案对其他人有所帮助:-)。

首先,如果你想保存没有User的Cars,你应该像下面这样保存Cars实体。

public class Car
{
public int Id { get; set; }
public int Year { get; set; }
public string Plate { get; set; }
// navigation property make nullable
public int? UserId { get; set; }
public User User { get; set; }
}

如果你想保存用户,在这种情况下,用户必须存在于数据库中。例如,在您的示例中,User必须存在于id=2的数据库中

最新更新