saeef ahmed
saeef ahmed

Reputation: 761

Entity Framework Core Put Operation Not Working

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; }
}

Upvotes: 0

Views: 1776

Answers (1)

clarkitect
clarkitect

Reputation: 1730

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());

Upvotes: 2

Related Questions