我正在使用基于API的实施框架的实施;在发送给客户端之前,EF对象被转换为DTO(数据传输对象)。ObjectStateEntry不更新,直到我检查db.Entry
在回来的路上,我正在从DTO改回我的实体类型;我在DELETE/UPDATE调用上遇到并发检查问题。我正在使用EF 6和webAPI 2.
发生什么事情是,在从数据库加载对象后,我必须在对象状态条目实际更改为'修改'之前调用db.Entry(object) 。
代码:
[Route("")]
[HttpDelete]
[ResponseType(typeof(void))]
public async Task<IHttpActionResult> DeleteAssetType(long id, DateTimeOffset modifyDate)
{
try
{
AssetType assetType = await db.AssetTypes.FindAsync(id);
if (assetType == null)
{
return NotFound();
}
//Set modifyDate to match what API received and then mark record for deletion
ObjectStateEntry ose = ((IObjectContextAdapter) db).ObjectContext.ObjectStateManager.GetObjectStateEntry(assetType);
assetType.ModifyDate = modifyDate;
ose.AcceptChanges();
db.AssetTypes.Remove(assetType);
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
//TODO Handle Concurrency Exception Specifically (if needed)
throw;
}
}
catch(Exception ex)
{
//TODO Add Error Handling Code
throw;
}
//return Ok(assetType);
return Ok();
}
...而问题是,呼叫assetType.ModifyDate = modifyDate(这是我的并发模式)后,如果我看ose.State,它的 “不变” 。但是,如果通过调试器,我查看db.Entry(assetType),然后看看ose,那么这个点就会正确地说出“Modified”。
核心问题是对ose.AcceptChanges()的调用什么也不做,因为它将对象视为未修改。
我可以通过调用db.Entry(assetType)来解决这个问题,并且对结果对象做任何事情都没有,并且从这一点起,它完美地工作,但是这似乎表明我在其他地方做错了什么, FindAsync声称它将实体附加到上下文,因此我不应该在询问状态之前调用.Entry。
由于我的意思扩展的例子,如果我做到以下几点:
...
assetType.ModifyDate = modifyDate;
var state = db.Entry(assetType).State; /* ADDED THIS LINE */
ose.AcceptChanges();
....
...然后调用ose.AcceptChanges()不正是我所期望的。我的问题是:为什么我必须调用db.Entry(assetType)才能使系统看到已更改的对象?它是否已经通过之前的FindAsync附加到上下文中,它是否应该不会自动接受对modifyDate的更改?如果它很重要,这是db-first与edmx文件,而不是代码第一。
编辑:修改为包含删除API函数的完整代码。
编辑2:澄清我要求/是什么使这项工作/问题是什么。
这个作品的意思是国家确实说“修改”。但是,我正在努力解决的问题是我的意思是删除;我想要做的是从数据库中删除对象如果数据库中的modify-date字段与API收到的内容匹配。 我会修改我的问题,使其更清楚一点 - 我遇到的问题是,我似乎必须调用db.Entry(assetType),无论我如何处理调用的结果,在状态实际上正确地将其自身设置为修改。 – SooperGenius