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! :)