user1027620
user1027620

Reputation: 2785

EntityFramework Nested Objects Update

What is so wrong about the below that the nested object never updates?

[Route("api/branches/{id}/devices")]
public async Task<IHttpActionResult> PutDevice(int id, Device device)
{
    Branch branch = await  db.Branches.Include("devices").FirstAsync(b => b.id == id);
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    if (branch == null)
    {
        return NotFound();
    }

    device.branch = branch;

    try
    {
        await db.SaveChangesAsync();
    }

    catch (DbUpdateConcurrencyException)
    {
        if (!BranchExists(id))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }
    return StatusCode(HttpStatusCode.NoContent);
}

I'm just passing a device object, and the branch ID. All i'm trying to do is to update a device's branch... However, the value never changes.

What am I missing?

Device.cs

public class Device
{
    public Device()
    {
        date_created = DateTime.UtcNow;
    }

    [Key]
    public int id { get; set; }
  
    public string name { get; set; }
    
    public virtual Branch branch { get; set; }

    public int branch_id { get; set; }

Upvotes: 5

Views: 3364

Answers (2)

Alberto Monteiro
Alberto Monteiro

Reputation: 6229

Your variable device isn't in EF context, so EF doesnt know about it, and he will never change the device.

You can try something like this:

[Route("api/branches/{id}/devices")]
public async Task<IHttpActionResult> PutDevice(int id, Device device)
{
    Branch branch = await  db.Branches.Include("devices").FirstAsync(b => b.id == id);
    Device dbDevice = await  db.Devices.Find(device.id);
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    if (branch == null || dbDevice == null)
    {
        return NotFound();
    }

    dbDevice.branch = branch;

    try
    {
        await db.SaveChangesAsync();
    }

    catch (DbUpdateConcurrencyException)
    {
        if (!BranchExists(id))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }
    return StatusCode(HttpStatusCode.NoContent);
}

Upvotes: 2

Reza Aghaei
Reza Aghaei

Reputation: 125292

You received the device from post values and it is not tracked by context. So when you call db.SaveChanges the context doesn't see any changes.

As you mentioned in comments, you have branch_id in device class, you can set the id to branch_id and you don't need to perform a query to load a branch at all.

To add a new device:

device.branch_id = id;   
db.Devices.Add(device);
db.SaveChanges();

To edit an existing device:

device.branch_id = id;   
db.Entry(device).State = EntityState.Modified;
db.SaveChanges();

Upvotes: 5

Related Questions