在检查db.Entry

时间:2017-01-09 16:47:57

标签: c# entity-framework asp.net-web-api2

我正在为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:阐明我要求的内容/使这项工作成为什么/问题是什么。

1 个答案:

答案 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)将一个实体标记为已删除,所以我认为这不是你想要的。