EF6 merge entity from WebApi
-
20-12-2019 - |
Question
I've been tasked with the glorious mission of modernizing a CRUD system (Ironic). I'm using EF 6.1.1 and WebApi. I send the Entity using a DTO (dynamic object for now will create a static type when all is working, will also make the calls async
)
[HttpGet]
public dynamic Get(int id)
{
var p = personRepository.Get(id);
return new
{
p.PersonId,
p.BirthYear,
p.DeathYear,
p.Comment,
PersonNames = p.PersonNames.Select(pn => new { pn.PersonId, pn.PersonNameId, pn.NameTypeId, pn.Firstname, pn.Prefix, pn.Surname })
};
}
I then update fields on the Person
object or add/remove/update PersonNames
collection using Knockout
and ko.mapping
I post the result to this WebApi method
[HttpPost]
public void Post([FromBody]Person person)
{
personRepository.Merge(person);
}
All the id's etc are correct, in personRepository.Merge
i've tried
public void Merge(Person person)
{
db.People.AddOrUpdate(person);
db.SaveChanges();
}
This works for the fields directly on the personobject, but it does not work with add/remove/update on the PersonNames
Can I support this without writing manual merge code?
Solution Ended up doing this
public void Merge(Person person)
{
db.People.AddOrUpdate(person);
var existingNames = db.PersonNames.Where(pn => pn.PersonId == person.PersonId).ToList();
var deleted = existingNames.Where(pn => person.PersonNames.All(d => d.PersonNameId != pn.PersonNameId));
db.PersonNames.RemoveRange(deleted);
foreach (var name in person.PersonNames)
{
db.PersonNames.AddOrUpdate(name);
}
db.SaveChanges();
}
Solution
Given you've mentioned this is a CRUD system this all looks sensible to me. I can't see how you can really avoid mapping from your DTO's back to your domain entities (e.g. Person)
I expect you've thought of it already, but how about removing as much boiler plate merge code as possible using something like AutoMapper? https://github.com/AutoMapper/AutoMapper
Mapping does get complicated for navigational properties (i.e. mapping between an object graph of DTO's back to an object graph of entities). This link goes into far more detail than I can: http://rogeralsing.com/2013/12/01/why-mapping-dtos-to-entities-using-automapper-and-entityframework-is-horrible/