我正在使用 ASP.NET WebApi 2 和 Entity Framework 6.1.0-alpha1 编写一个简单的“Todo App”。我的目标是限制访问,每个用户只能查看/编辑他们自己的待办事项。
例子:
// GET api/Todo/5
[ResponseType(typeof(Todo))]
public async Task<IHttpActionResult> GetTodo(int id)
{
var todo = await _db.Todos.FindAsync(id);
if (todo == null)
{
return NotFound();
}
if (todo.CreatorId != _currentUser.Id)
{
return StatusCode(HttpStatusCode.Forbidden);
}
return Ok(todo);
}
那也行。为删除添加了类似的检查,并在创建时将 CreatorId 设置为当前用户的 ID。但是,我在更新时遇到了问题。
我试过这个:
// PUT api/Todo/5
public async Task<IHttpActionResult> PutTodo(int id, Todo todo)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != todo.Id)
{
return BadRequest();
}
// --- No exception if I remove this block - BEGIN ---
var original = await _db.Todos.FindAsync(id);
if (original.CreatorId != _currentUser.Id || original.CreatorId != todo.CreatorId)
{
return StatusCode(HttpStatusCode.Forbidden);
}
// --- No exception if I remove this block - END ---
_db.Entry(todo).State = EntityState.Modified; // Exception thrown here
try
{
await _db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TodoExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
但是,System.InvalidOperationException
它抛出了标记线:
System.InvalidOperationException
附加类型为“ModernWeb.Domain.Models.Todo”的实体失败,因为同一类型的另一个实体已经具有相同的主键值。如果图中的任何实体具有冲突的键值,则在使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新实体,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“已添加”实体状态来跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”。
如果我使用 FindByAsync() 删除块,它不会抛出异常。
我也尝试使用_db.Entry(todo).OriginalValue
,但找不到有效的语法。
我该如何克服这个问题?对于这种情况有什么最佳实践吗?