首页 > 解决方案 > 尝试向表中添加行时无法将 Int32 转换为 null

问题描述

我正在尝试向具有指向同一个表中另一个位置的外键的表中添加一行。此外键被定义为可为空的。尝试向表中添加条目时,出现错误

"errors": {
    "parentId": [
      "Error converting value {null} to type 'System.Int32'. Path 'parentId', line 4, position 18."
    ]
  },

如果我尝试传递一个随机整数,我会得到The INSERT statement conflicted with the FOREIGN KEY constraint,这是有道理的,因为表中没有其他条目。 可为空的

如您所见,外键被视为可为空的。

我试过根本不传递字段,传递字段时不传递任何参数,传递null,所有这些都会产生后来的错误,除了我尝试传递null时,这给了我转换错误。

我正在使用 swagger ui 来传递 JSON。

有问题的班级:

public class 
{
    public Country Country { get; set; }
    [Required]
    public int CountryId { get; set; }
    [Required]
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }
    public int? ParentId { get; set; }
    [ForeignKey("ParentId")]
    public Company Parent { get; set; }     
}

我想在这个表上创建第一行并将它的外键设置为空。

在实施答案中建议的修复后,我的错误从转换错误转变为上述外部约束错误,即使传递空值也是如此。

代码,根据要求:

数据库上下文:

public class ArtGalleriesContext:DbContext
{
    public ArtGalleriesContext(DbContextOptions<ArtGalleriesContext> options):base(options)
    {

    }

    public DbSet<ArtItem> ArtItems { get; set; }
    public DbSet<Artist> Artists { get; set; }
    public DbSet<Company> Companies { get; set; }
    public DbSet<Country> Countries { get; set; }
    public DbSet<Floor> Floors { get; set; }
    public DbSet<Location> Locations { get; set; }
    public DbSet<Room> Rooms { get; set; }
    public DbSet<User> Users { get; set; }
    public DbSet<UserLocation> UserLocations { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {

        modelBuilder.Entity<UserLocation>()
            .HasKey(u => new {u.UserId, u.LocationId});
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer(
                "Server=(localdb)\\mssqllocaldb;Database=GalleriesDB;Trusted_Connection=True;");
        }
    }
}

控制器:

[HttpPost("Companies")]
public IActionResult CreateCompany([FromBody]CreateCompanyRequest createCompanyRequest)
{
    try
    {
        if (createCompanyRequest==null)
        {
            return NotFound();
        }

        return CreatedAtRoute("CompanyById", _repository.Company.CreateCompany(createCompanyRequest),
            createCompanyRequest);
    }
    catch (Exception e)
    {
        return StatusCode(500, e.InnerException);
    }
}

存储库:

public int CreateCompany(CreateCompanyRequest createCompanyRequest)
{
    Company company = new Company()
    {
        CountryId = createCompanyRequest.CountryId,
        Name = createCompanyRequest.Name,
        ParentId = createCompanyRequest.ParentId
    };
    _context.Companies.Add(company);
    _context.SaveChanges();
    return company.Id;
}

可能相关信息:我尝试使用 Microsoft SQL Server Manager 填充表。它是成功的,然而,结果是这样的:

奇怪的身份证

显然有问题,因为它从 PK 14 开始添加条目。

经过进一步检查,我注意到即使向表中添加行失败,主键仍然会增加。

标签: c#sql-serveref-core-2.2

解决方案


错误在于将 json 反序列化为模型,这里有两个选项:

  1. 添加到您的 startup.cs 类 Json 选项以忽略空值,如下所示:

    .AddJsonOptions(options =>
     {
         options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore
     });
    
  2. 在属性本身上设置以忽略 null 值,因此它将初始化int?为 null

    public class 
    {
       public Country Country { get; set; }
       [Required]
       public int CountryId { get; set; }
       [Required]
       public int Id { get; set; }
       [Required]
       public string Name { get; set; }
       [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
       public int? ParentId { get; set; }
       [ForeignKey("ParentId")]
       public Company Parent { get; set; }     
    }
    

推荐阅读