Entity Framework Core Put Operation Not Working

asp.net-web-api c# entity-framework entity-framework-core

Question

I am getting

Unhandled Exception Error: the property 'Id' on entity type 'Vehicle' is part of a key and so cannot be modified or marked as modified. To change the principal of an existing entity with an identifying foreign key first delete the dependent and invoke 'SaveChanges' then associate the dependent with the new principalThe property 'Id' on entity type 'Vehicle' is part of a key and so cannot be modified or marked as modified. To change the principal of an existing entity with an identifying foreign key first delete the dependent and invoke 'SaveChanges' then associate the dependent with the new principal

Here is my Put API:

[HttpPut("{id}")]
public IActionResult UpdateVehicle(int id, [FromBody] SaveVehicleResource vehicleResource)
{
        if (!ModelState.IsValid)
            return BadRequest(ModelState);

        var vehicle = context.Vehicles.Include(v => v.Features).SingleOrDefault(v => v.Id == id);

        if (vehicle == null)
            return NotFound();

        mapper.Map(vehicleResource, vehicle);
        vehicle.LastUpdate = DateTime.Now;

        context.SaveChanges();

        var result = mapper.Map<Vehicle, SaveVehicleResource>(vehicle);

        return Ok(result);
}

Here is DbContext:

public class VegaDbContext : DbContext
{
    public DbSet<Make> Makes { get; set; }
    public DbSet<Feature> Features { get; set; }
    public DbSet<Vehicle> Vehicles { get; set; }
    public DbSet<Model> Models { get; set; }

    public VegaDbContext(DbContextOptions<VegaDbContext> options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<VehicleFeature>().HasKey(vf => new { vf.VehicleId, vf.FeatureId });
    }
}

Vehicle class:

public class Vehicle
{
    public int Id { get; set; }
    public int ModelId { get; set; }
    public Model Model { get; set; }
    public bool IsRegistered { get; set; }
    public Contact Contact { get; set; }
    public ICollection<VehicleFeature> Features { get; set; }
    public DateTime LastUpdate { get; set; }
    public Vehicle()
    {
        Features = new Collection<VehicleFeature>();
    }
}

VehicleFeature class:

public class VehicleFeature
{
    public int VehicleId { get; set; }
    public int FeatureId { get; set; }
    public Vehicle Vehicle { get; set; }
    public Feature Feature { get; set; }
}
1
0
8/29/2018 4:48:13 AM

Accepted Answer

Disclaimer: it really looks like you're using AutoMapper. So let's take a look at your AutoMapper configuration. Specifically, see if you can find something like .CreateMap<Vehicle, SaveVehicleResource> in there.

One of these two things is happening:

  1. Your AutoMapper is configured to explicitly CreateMap for these classes and it includes a statement similar to .ForMember(x => x.Id, x.MapFrom(y => y.Id))
  2. Your AutoMapper is not configured explicitly which means it is finding the property .Id because both classes define it with the same name. You must explicitly ignore that member.

Regardless which of those things has happened, you'll have to tell AutoMapper to ignore that property.

CreateMap<Vehicle, SaveVehicleResource>(...)
    .ForMember(x => x.Id, y => y.Ignore());
1
8/29/2018 2:22:14 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow