我正在开发一个WebAPI v2操作方法,以使用Entity Framework 6持久更新对象图,我有点不确定我是否有正确的语法。 Project 是我的根类型,其中包含 Question 的集合。 Project 已经存在,但Post操作可能需要提交对 Project 属性的更改,对现有 Question 的更改并添加新< EM>问题的
我的代码在下面显示和评论,但是当我想要有一个帮助方法可以为我做一些帮助时,更新需要大量的工作:
[System.Web.Http.Route("{id:int}")]
public HttpResponseMessage Post(int id, [FromBody]Project project)
{
// Validate the submitted project
if (!ModelState.IsValid)
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
// Fetch the existing project. This is here to perform row-level
// security check. The user will have logged on and this confirms the
// organisation they work for. Behind the scenes I will compound the
// query below to include a check for organisation id. This prevents
// users submitted any project id and overwriting data that isn't theirs.
// Would it make the pattern below better if this only executed a .Count()?
// Would that mean the context would then be tracking the project before
// the update?
var existingProject = _context.Projects.Include("Questions").FirstOrDefault(p => p.ProjectId == id);
if (existingProject == null)
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ModelState);
// Copy model updates to the project
var projectEntry = _context.Entry(existingProject);
projectEntry.CurrentValues.SetValues(project);
// Now work out which questions are updates or additions
foreach (var question in project.Questions)
{
// No id so must be an addition
if (question.QuestionId == 0)
{
existingProject.Questions.Add(question);
}
else
{
// Fetch the existing question so we can copy values
var existingQuestion = existingProject.Questions.FirstOrDefault(q => q.QuestionId == question.QuestionId);
if (existingQuestion == null)
{
// In a single user system finding ourselves here should not
// be possible. Ideally we'll need to do some concurrency
// when other users make updates or have some record locking
// mechanism.
existingProject.Questions.Add(question);
}
else
{
var questionEntry = _context.Entry(existingQuestion);
questionEntry.CurrentValues.SetValues(question);
}
}
}
_context.SaveChanges();
return Request.CreateResponse(HttpStatusCode.Created, project);
}
更新:我在提交之后也意识到我甚至没有处理删除问题的问题,但是看看上面的解决方案,我不会目前正在照顾,所以我很感激被考虑。
答案 0 :(得分:0)
看起来你正在寻找Trackable-Entities,这里是wiki标题:
可跟踪实体支持跟踪对象图中实体的更改,以便将它们发送到Web服务并保存在单一往返和< em>单笔交易。此功能作为一组NuGet packages提供。
服务器端NuGet包为Entity Framework的ApplyChanges
类提供DbContext
扩展方法,该类遍历一个或多个对象图,通知实体框架每个实体的更改状态。调用SaveChanges
后,您可以调用AcceptChanges
将所有实体的状态设置为Unchanged
,然后再将其返回给客户端。还有一个LoadRelatedEntities
方法,您可以调用该方法来填充已添加实体的参考属性。
客户端软件包提供更改跟踪器,用于在将实体插入,修改或删除时将实体标记为Added
,Modified
或Deleted
对象图中的任何级别。要开始跟踪更改,只需将一个或多个实体添加到ChangeTrackingCollection
,然后将Tracking
属性设置为true
即可。如果要保留更改,可以在更改跟踪器上调用GetChanges
以仅获取更改的项目,这样就不需要将未更改的实体发送到服务器,从而节省带宽并提高性能。可跟踪实体将关联实体,以便您可以通过调用MergeChanges
将更新的实体合并回原始对象图。虽然您当然可以手动设置TrackingState
实体,但更改跟踪器部署为可移植类库,因此您可以从任何.NET客户端(包括桌面或移动应用程序)使用它。 / p>
另一个需要考虑的项目是Breeze#。