EF core 构建的 .NET core API 中 Swagger 所需字段错误

问题描述 投票:0回答:1

我是.NET core 的初学者。我有两个实体,实体技术和实体技能。每个Tech都有一个Skill列表,Skill有Tech的外键。数据库是用EF core构建的。

实体是这样的:

Tech.cs

public class Tech
{
    [Key]
    public int Id { get; set; }
    public string TechName { get; set; }
    public virtual ICollection<Skill> Skills { get; set; } = new List<Skill>();
    // for soft delete
    public bool isDeleted { get; set; }
}

技能.cs

public class Skill
{
    [Key]
    public int Id { get; set; }
    public string SkillName { get; set; }
    // Foreign Key
    [Required]
    public int TechId { get; set; }
    [ForeignKey("TechId")]
    [JsonIgnore]
    public Tech tech { get; set; }
    // For soft delete

    public bool isDeleted { get; set; }
}

数据库上下文:

为了技能

public void Configure(EntityTypeBuilder<Skill> builder)
{
    builder.ToTable("Skill");
    builder.HasKey(x => x.Id);
    builder.Property(t => t.Id).IsRequired().ValueGeneratedOnAdd();
    builder.Property(x => x.SkillName).HasColumnType("nvarchar(50)");
    builder.HasQueryFilter(b => !b.isDeleted);
    builder
        .HasOne(e => e.tech)
        .WithMany(e => e.Skills).HasForeignKey(e => e.TechId).OnDelete(DeleteBehavior.Cascade); ;

    ICollection<Skill> skill_1 = new List<Skill>();
    skill_1 = AddDotNetSkill();

    builder.HasData(skill_1);
}

对于科技

public void Configure(EntityTypeBuilder<Tech> builder)
{
    builder.ToTable("Tech");
    builder.HasKey(t => t.Id);
    builder.Property(t => t.Id).IsRequired().ValueGeneratedOnAdd();
    builder.Property(x => x.TechName).HasColumnType("nvarchar(50)");
    builder.HasQueryFilter(b => !b.isDeleted);



    Tech tech_1 = AddTechDotNet();
    Tech tech_2 = AddTechDatabases();

    builder.HasData(tech_1);
    builder.HasData(tech_2);
}

因此我尝试使用这两个实体创建一个 CRUD API。 get 方法很好,但是当我尝试执行 HttpPost 时,Swagger 会立即回复 400 错误,而无需进入我的控制器。

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "00-0c523d52d0f3f06ce2a64fe8fe59520a-974d7fc666a3a246-00",
  "errors": {
    "Skills[0].tech": [
      "The tech field is required."
    ]
  }
}

以下是我的控制器:

// POST: api/Techs
[HttpPost]
public ActionResult<Tech> PostTech([FromBody] Tech tech)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    _context.Techs.Add(tech);
    _context.SaveChanges();

    foreach (var skill in tech.Skills)
    {
        skill.TechId = tech.Id;
        _context.Add(skill);
        _context.SaveChanges();
    }

    return Ok(tech);
}

我认为问题出在我的 Tech tech 外键上,如果我能收到任何与此相关的建议,我将非常感激。

.net entity-framework-core swagger crud
1个回答
0
投票

通过这样配置模型,EF Core 在它们之间创建“一对多”关系。不需要在FluentApi中明确指出关系(仅针对一对一的需要)

public class Tech
{
    //Best way to initialize the collection directly in the model
    public Tech()
    {
        this.Skills = new HashSet<Skill>();
    }

    [Key]
    public int Id { get; set; }
    [MaxLength(50)] //nvarchar(50)
    public string TechName { get; set; }
    public bool isDeleted { get; set; }
    
    // Relation to Skills 
    public virtual ICollection<Skill> Skills { get; set; };
}

public class Skill
{
    [Key]
    public int Id { get; set; }
    [MaxLength(50)] //nvarchar(50)
    public string SkillName { get; set; }
    public bool isDeleted { get; set; }

    //Relation to Tech
    public int TechId { get; set; }
    public Tech Tech { get; set; }
    
}

控制器

[HttpPost]
[ProducesResponseType(typeof(Tech), 200)] //Specifind in the swagger the object your method receive
public async Task<ActionResult<Tech>> PostTech([FromBody] Tech tech)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    
    //Here you add the Tech in Techs table and all skills in the Skills table, no need separate save for skills
    await _context.AddAsync(tech);
    await _context.SaveChangesAsync();

    return Ok(tech);
}

您收到的错误 400 意味着您的 json 数据无法反序列化为 Tech 对象。我在发送到

PostTech
的对象中看到,您在
"id": 3
中传递了
"techId": 3
Slill
,但是如果您使用代码优先方法 EF 创建 Id 作为身份,这意味着您必须将
Id
保留为 null 相同对于技能

© www.soinside.com 2019 - 2024. All rights reserved.