如何使用实体框架在WebAPI操作中提交对象图



我正在开发一个WebAPI v2操作方法,以使用Entity Framework 6持久更新对象图,我有点不确定我是否有正确的语法Project是我的根类型,它包含问题的集合。项目将已经存在,但发布操作可能需要提交对工程属性的更改、对现有问题的更改以及添加新的

下面显示并评论了我的代码,但当我想有一种辅助方法可以为我做一些事情时,更新需要做很多工作:

[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);
}

更新:我在提交这篇文章后也意识到,我甚至还没有处理删除问题的问题,从我上面的解决方案来看,目前还不能满足这些问题,所以我也很感激大家的考虑。

看起来你正在寻找可跟踪实体,这里是它的wiki标题:

可跟踪实体支持跟踪对象图中实体的更改,以便将其发送到web服务,并在单次往返单个事务中持久化。此功能是作为一组NuGet软件包提供的。

服务器端NuGet包为Entity Framework的DbContext类提供了一个ApplyChanges扩展方法,该方法遍历一个或多个对象图,向Entity Framework通知每个实体的更改状态。调用SaveChanges之后,您可以调用AcceptChanges将所有实体的状态设置为Unchanged,然后再将它们返回到客户端。还有一个LoadRelatedEntities方法,您可以调用它来填充已添加实体的引用属性。

客户端软件包提供更改跟踪器,用于在对象图中的任何级别插入、修改或删除实体时,将其标记为AddedModifiedDeleted。要开始跟踪更改,只需向ChangeTrackingCollection添加一个或多个实体,并将Tracking属性设置为true。当您想要持久化更改时,可以在更改跟踪器上调用GetChanges,只获取更改的项目,这样就不需要将未更改的实体发送到服务器,从而节省带宽并提高性能。可跟踪实体将关联实体,以便您可以通过调用MergeChanges将更新的实体合并回原始对象图。虽然您当然可以手动在实体上设置TrackingState,但更改跟踪器被部署为可移植类库,因此您可以从任何位置使用它。NET客户端,包括桌面或移动应用程序。

另一个需要考虑的项目是Breeze#。

最新更新