简体   繁体   中英

EF Core 6 error "System.ArgumentNullException: Value cannot be null. (Parameter 'key')" using API method POST and PUT

I have an error "Value cannot be null (Parameter key)" using post and put methods.

So I have to send data using a Radzen Blazor dialog

I found that my many to many relationships between (product and predefinedElements), (markets and predefinedElements) and (actuation type and predefinedelements) cause "value cannot be null" exception but I can't find what's null here...

Here is how market, predefinedElements, products and actuationType are defined in the Model

Market:

namespace BTNLib.Shared.Models
 {
  public partial class Market
  {
    public Market()
    {
        PredefinedElements = new HashSet<PredefinedElement>();
    }

    [Key]
    public int MarketId { get; set; }
    public string? Name { get; set; }

    
    [InverseProperty(nameof(PredefinedElement.Markets))]
    public virtual ICollection<PredefinedElement> PredefinedElements { get; set; }
  }
}

PredefinedElement:

namespace BTNLib.Shared.Models
{
  public partial class PredefinedElement
 {
    public PredefinedElement()
    {
        ActuationTypes = new HashSet<ActuationType>();
        Markets = new HashSet<Market>();
        Products = new HashSet<Product>();
    }

  

    public string? SpoolRSideStd { get; set; }  
    [Key]
    
    public int PredefinedElementId { get; set; }
    public string? Designation { get; set; }
    public string? ConfigFileLink { get; set; }
    public string? SpoolRSideRs15Rs12 { get; set; }
    public string? SpoolRSideRs12Rs08 { get; set; }
    public int? SectionElementPositionId { get; set; }
    public int? MaxFlow { get; set; }
    public int? SectionElementTypeId { get; set; }
    public string? InternalPilotOilSupply { get; set; }
    public int? SectionBasicFunctionId { get; set; }
    public int? SectionMouvmeentNamingId { get; set; }
    public int? SectionCustomerPipingId { get; set; }
    public string? PortType { get; set; }
    public string? ConnectorType { get; set; }
    public string? Voltage { get; set; }
    public string? RpnSide { get; set; }
    public int? SliceTypeId { get; set; }
    public string? ShortInformation { get; set; }
    public string? LongInformation { get; set; }
    public string? Docupedia { get; set; }
    public string? SectionPicture { get; set; }
    public string? SectionPictureAxo { get; set; }
    public string? MasterConfigFile { get; set; }
    public string? Color { get; set; }
    public int? EfatemplateId { get; set; }
    public int? EfaAsmTemplateId { get; set; }
    public int? EfaAgzTemplateId { get; set; }
    public int? EfaGezTemplateId { get; set; }
    public int? TieRodThicknessSide1 { get; set; }
    public int? LThreadUnderNutSide1 { get; set; }
    public int? LThreadAfterNutSide1 { get; set; }
    public int? NutThicknessSide1 { get; set; }
    public int? InitialAnchorLenghSide1 { get; set; }
    public int? LThreadUnderNutSide2 { get; set; }
    public int? LThreadAfterNutSide2 { get; set; }
    public int? NutThicknessSide2 { get; set; }
    public int? InitialAnchorLenghSide2 { get; set; }




    public int? FlangeFaceInCavityId { get; set; }

   
    public int? FlangeFaceOut1CavityId { get; set; }

   
    public int? FlangeFaceOut2CavityId { get; set; }

    
    public int? RequiredFlangeFaceCavity1id { get; set; }

  
    public int? RequiredFlangeFaceCavity2id { get; set; }

    public int? RequiredFlangeFaceCavity3id { get; set; }

    
    public int? RequiredFlangeFaceCavity4id { get; set; }

  
    public int? RequiredFlangeFaceCavity5id { get; set; }


    public int? RequiredFlangeFaceCavity6id { get; set; }

    
    public int? RequiredFlangeFaceCavity7id { get; set; }

    public int? ImageId { get; set; }
    public string? Actuation { get; set; }

   
    public virtual EfaAgzTemplate? EfaAgzTemplate { get; set; }
    public virtual EfaAsmTemplate? EfaAsmTemplate { get; set; }
    public virtual EfaGezTemplate? EfaGezTemplate { get; set; }
    public virtual Efatemplate? Efatemplate { get; set; }
    public virtual Cavity? FlangeFaceInCavity { get; set; }
    public virtual Cavity? FlangeFaceOut1Cavity { get; set; }
    public virtual Cavity? FlangeFaceOut2Cavity { get; set; }
    public virtual Image? Image { get; set; }

    public virtual Cavity? RequiredFlangeFaceCavity1 { get; set; }

    public virtual Cavity? RequiredFlangeFaceCavity2 { get; set; }

    public virtual Cavity? RequiredFlangeFaceCavity3 { get; set; }

    public virtual Cavity? RequiredFlangeFaceCavity4 { get; set; }

    public virtual Cavity? RequiredFlangeFaceCavity5 { get; set; }

    public virtual Cavity? RequiredFlangeFaceCavity6 { get; set; }

    public virtual Cavity? RequiredFlangeFaceCavity7 { get; set; }

    public virtual SectionBasicFunction? SectionBasicFunction { get; set; }
    public virtual SectionCustomerPiping? SectionCustomerPiping { get; set; }
    public virtual SectionElementPosition? SectionElementPosition { get; set; }
    public virtual SectionElementType? SectionElementType { get; set; }
    public virtual SectionMouvementNaming? SectionMouvmeentNaming { get; set; }
    public virtual SliceType? SliceType { get; set; }

    

    [InverseProperty(nameof(ActuationType.PredefinedElements))]
    public virtual ICollection<ActuationType> ActuationTypes { get; set; }

    
    [InverseProperty(nameof(Market.PredefinedElements))]
    public virtual ICollection<Market> Markets { get; set; }

    
    [InverseProperty(nameof(Product.PredefinedElements))]
    public virtual ICollection<Product> Products { get; set; }
  } 
}

Product:

namespace BTNLib.Shared.Models
{
 public partial class Product
 {
    public Product()
    {
        PredefinedElements = new HashSet<PredefinedElement>();
    }
    
    [Key]
    public int ProductsId { get; set; }
    public string? Name { get; set; }

    [InverseProperty(nameof(PredefinedElement.Products))]
    public virtual ICollection<PredefinedElement> PredefinedElements { get; set; }
   }
 }

Actuation Type:

namespace BTNLib.Shared.Models
{
 public partial class ActuationType
  {
    public ActuationType()
    {
        PredefinedElements = new HashSet<PredefinedElement>();
    }

    [Key]
    public int ActuationTypeId { get; set; }
    public string? Type { get; set; }

    [InverseProperty(nameof(PredefinedElement.ActuationTypes))]
    public virtual ICollection<PredefinedElement> PredefinedElements { get; set; }
  }
}

The database context is too long to be posted here if you need it I can post it in repsonse.

When I send the data of the predefinedElement is like that:

 protected async Task Submit()
  {
    if (Designation == null)
    {
        await PredefinedElementService.CreatePredefinedElement(predefinedElement);
    }
    else
    {
        await PredefinedElementService.UpdatePredefinedElement(predefinedElement);
    }
}


void OnChangeMarket(IEnumerable<Market> values)
{
    predefinedElement.Markets.Clear();
    foreach(var Market in values)
    {
        predefinedElement.Markets.Add(Market);
    }
}

void OnChangeProduct(IEnumerable<Product> values)
{
    predefinedElement.Products.Clear();
    foreach(var Product in values)
    {
        predefinedElement.Products.Add(Product);
    }
}

void OnChangeActuationType(IEnumerable<ActuationType> values)
{
    predefinedElement.ActuationTypes.Clear();
    foreach(var ActuationType in values)
    {
        predefinedElement.ActuationTypes.Add(ActuationType);
    }
 }

It calls Post or Put method via a service like that:

  public async Task CreatePredefinedElement(PredefinedElement predefinedElement)
    {

        var result = await _http.PostAsJsonAsync("api/PredefinedElements", 
         predefinedElement);
        Console.WriteLine(result);

       await SetPredefinedElement(result);
    }

 public async Task UpdatePredefinedElement(PredefinedElement predefinedElement)
    {


        var result = await 
 _http.PutAsJsonAsync($"api/PredefinedElements/{predefinedElement.PredefinedElementId}", 
  predefinedElement);
        await SetPredefinedElement(result);
    }

And the controller API is something like that: The error is displayed when _context.Add or _context.Update are called

[HttpPost]
public  async Task<ActionResult<List<PredefinedElement>>> 
     PostPredefinedElement(PredefinedElement predefinedElements)
    {

        try
        {
           
            _dbContext.PredefinedElements.Add(predefinedElements);
        }
        catch(Exception ex)
        {
            throw ex;
        }
       
        await _dbContext.SaveChangesAsync();


        return Ok(await GetdbPredefinedElement());
    }


[HttpPut("{id}")]
public async Task<ActionResult<List<PredefinedElement>>> 
   UpdatePredefinedElement(PredefinedElement predefinedElement)
    {
       
        if (predefinedElement == null)
        {
            return NotFound("Aucun element de ce type");
        }
        else
        {

            _dbContext.Update(predefinedElement);
        }
        
        await _dbContext.SaveChangesAsync();

        return Ok(await GetdbPredefinedElement());
    }


private async Task<List<PredefinedElement>> GetdbPredefinedElement()
    {
        var result = await _dbContext.PredefinedElements.Include(p => p.Products)
            .Include(p => p.Markets)
            .Include(p => p.ActuationTypes)
            .Include(p => p.Image)
            .Include(p => p.SectionElementPosition)
            .Include(p => p.SectionElementType)
            .Include(p => p.SectionBasicFunction)
            .Include(p => p.SectionMouvmeentNaming)
            .Include(p => p.SectionCustomerPiping)
            .Include(p => p.SliceType)
            .Include(p => p.Efatemplate)
            .Include(p => p.EfaAgzTemplate)
            .Include(p => p.EfaAsmTemplate)
            .Include(p => p.EfaGezTemplate)
            .Include(p => p.FlangeFaceInCavity)
            .Include(p => p.FlangeFaceOut1Cavity)
            .Include(p => p.RequiredFlangeFaceCavity1)
            .Include(p => p.RequiredFlangeFaceCavity2)
            .Include(p => p.RequiredFlangeFaceCavity3)
            .Include(p => p.RequiredFlangeFaceCavity4)
            .Include(p => p.RequiredFlangeFaceCavity5)
            .Include(p => p.RequiredFlangeFaceCavity6)
            .Include(p => p.RequiredFlangeFaceCavity7).ToListAsync();
      
        return result;
        

    }

I can't figure out what cause the exception I only know that came from many to many relationships because when I don't add entity from this relationship in the collection there are no error displayed.

I tried everything like putting [key] everywhere in the model checking my DB if there was no problem.

This project is a merge from 2 projects so there is another database context where 2 tables are linked with the first context.

EDIT: the error only happens when I try to post another predefinedelement entity or modify one resulting two entities of predefinedelement have the same entity from the table Market, Product or ActuationType.

Exemple in the Joining Table Predefinedelement_Market

PredefinedElementId: 1 MarketId: 1 and PredefinedElementId: 2 MarketId: 1
causing the error in Entity Framework

Thanks for the help.

SOLVED:

So to prevent this error you need to had to the controller before adding the element and saving:

predefinedElements.Markets = _dbContext.Markets.Where(x => predefinedElements.Markets.Contains(x)).ToList();
predefinedElements.Products = _dbContext.Products.Where(x => predefinedElements.Products.Contains(x)).ToList();
predefinedElements.ActuationTypes = _dbContext.ActuationTypes.Where(x => predefinedElements.ActuationTypes.Contains(x)).ToList();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM