Update Children and Grand Children in ASP.NET WebAPI 2 Entity Framework

时间:2016-04-04 17:20:39

标签: asp.net entity-framework asp.net-web-api2

I'm trying to build a WebAPI with ASP.NET and have the following models:

Machine:

public class Machine
{
    public Machine()
    {
        this.Disks = new HashSet<Disk>();
    }

    public long Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Disk> Disks { get; set; }
    public long Status { get; set; }
}

Disk:

public class Disk
{
    public Disk()
    {
        this.Partitions = new HashSet<Partition>();
    }

    public long Id { get; set; }
    public string ControllerName { get; set; }
    public string InterfaceType { get; set; }
    public long Size { get; set; }
    public long Index { get; set; }

    public virtual ICollection<Partition> Partitions { get; set; }

    [ForeignKey("Machine")]
    public long MachineId { get; set; }

    public virtual Machine Machine { get; set; }
}

Partition:

public class Partition
{
    public long Id { get; set; }
    public long Size { get; set; }
    public long Index { get; set; }

    [ForeignKey("Disk")]
    public long DiskId { get; set; }

    public virtual Disk Disk { get; set; }

}

Now I'm trying to implement the PutMachine-Method in MachineController, which should also update the Disks and Partitions. I tried so many "solution" but none of them worked for me. Either my Disks will not be updated or I get an 500 Error, (i.e. "Attaching an entity of type [...] failed because another entity of the same type already has the same primary key value.")

My MachineController PutMachine looks like this:

// PUT: api/Machines/5
    [ResponseType(typeof(void))]
    public async Task<IHttpActionResult> PutMachine(long id, Machine machine)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        if (id != machine.Id)
        {
            return BadRequest();
        }

        if( machine.Disks != null )
        {
            foreach (Disk disk in machine.Disks)
            {
                var di = await db.Disks.Where(d => d.MachineId == machine.Id && d.Index == disk.Index).FirstOrDefaultAsync();
                if (di == null)
                {
                    disk.MachineId = id;
                    db.Entry(disk).State = EntityState.Added;
                }
                else
                {
                    //disk.MachineId = id;
                    //db.Entry(di).CurrentValues.SetValues(disk);
                    //db.Entry(disk).State = EntityState.Modified;
                    //db.Disks.Attach(disk);
                    disk.MachineId = id;
                    db.Entry(di).State = EntityState.Deleted;
                    db.Entry(disk).State = EntityState.Added;
                }

                if (disk.Partitions != null)
                {
                    foreach (Partition partition in disk.Partitions)
                    {
                        var pa = await db.Partitions.Where(p => p.DiskId == disk.Id && p.Index == partition.Index).FirstOrDefaultAsync();
                        if (pa == null)
                        {
                            partition.DiskId = disk.Id;
                            db.Entry(partition).State = EntityState.Added;
                        }
                        else
                        {
                            partition.DiskId = disk.Id;
                            //db.Entry(partition).State = EntityState.Modified;
                            db.Partitions.Attach(partition);
                        }
                    }
                }
            }
        }


        db.Entry(machine).State = EntityState.Modified;

        try
        {
            await db.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MachineExists(id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return StatusCode(HttpStatusCode.NoContent);
    }

At the moment I leave the partitions in json data empty to get the disk update working first, bevor I go on. The solution with deleting disks and adding them again works at the moment, but can't be the way to go. In the commented lines you see code I tried before.

And finally my json (with the partitions part):

{
"Id": 2,
"Name": "test",
"Disks":  [
            {
                    "ControllerName":  "ATA Channel 0",
                    "Partitions":  [
                                        {
                                                "Size":  53686042624,
                                                "Index":  2
                                        },
                                        {
                                                "Size":  53317992448,
                                                "Index":  1
                                        },
                                        {
                                                "Size":  367001600,
                                                "Index":  0
                                        }
                    ],
                    "InterfaceType":  "IDE",
                    "Size":  107372805120,
                    "Index":  0
            }
      ],
}

I'll be glad about every solution to get this working. Thanks! :)

0 个答案:

没有答案