我正在为Entity Framework使用基于API的实现; EF对象在被发送到客户端消费之前被转换为DTO(数据传输对象)。
在回来的路上,我正在从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,它就会变为&#34;未变化&#34;。但是,如果通过调试器,我查看db.Entry(assetType),然后看看ose,那时ose会正确地说&#34;修改&#34;。
核心问题是对ose.AcceptChanges()的调用什么都不做,因为它将对象视为未修改。
我可以通过调用db.Entry(assetType)并对生成的对象执行字面上的NOTHING来解决这个问题,并且从那一点开始就可以完美地工作,但这似乎表明我在其他地方做错了,正如FindAsync声称它将实体附加到上下文中,因此在询问状态之前我不应该调用.Entry。
作为我的意思的扩展示例,如果我执行以下操作:
...
assetType.ModifyDate = modifyDate;
var state = db.Entry(assetType).State; /* ADDED THIS LINE */
ose.AcceptChanges();
....
...然后调用ose.AcceptChanges()完全符合我的预期。我的问题是为什么我必须调用db.Entry(assetType)以便系统将对象视为已更改?它是否尚未通过之前的FindAsync附加到上下文中,是否应该自动获取对modifyDate的更改?如果重要的话,这是带有edmx文件的db-first,而不是代码优先。
编辑:修改为包含删除API函数的完整代码。
编辑2:阐明我要求的内容/使这项工作成为什么/问题是什么。
答案 0 :(得分:0)
试试这个:
AssetType assetType = await db.AssetTypes.FindAsync(id); //get object from db
assetType.ModifyDate = modifyDate; //modify it
var state = db.Entry(assetType).State; //get current state, which should be Modified
var updatedRecords = await db.SaveChangesAsync();
问题似乎是您获得的状态是在对实体进行任何更改之前。 顺便说一句,方法Remove(https://msdn.microsoft.com/en-us/library/gg679171(v=vs.113).aspx)将一个实体标记为已删除,所以我认为这不是你想要的。