在ASP.Net Core文档中使用AsNoTracking

时间:2018-12-05 16:29:18

标签: c# entity-framework entity-framework-core

在ASP.Net Core文档的以下代码中,当我编辑实体时,我一直试图理解AsNoTracking的用法,发现here

public async Task<IActionResult> OnPostAsync(int id)
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    // Fetch Contact from DB to get OwnerID.
    var contact = await Context
        .Contact.AsNoTracking()
        .FirstOrDefaultAsync(m => m.ContactId == id);

    if (contact == null)
    {
        return NotFound();
    }

    var isAuthorized = await AuthorizationService.AuthorizeAsync(
                                             User, contact,
                                             ContactOperations.Update);
    if (!isAuthorized.Succeeded)
    {
        return new ChallengeResult();
    }

    Contact.OwnerID = contact.OwnerID;

    Context.Attach(Contact).State = EntityState.Modified;

    …

    await Context.SaveChangesAsync();

    return RedirectToPage("./Index");
}

AsNoTracking状态的摘要:

  

禁用更改跟踪对于只读方案很有用,因为它可以   避免了为每个实体设置变更跟踪的开销   实例。如果您想禁用更改跟踪   处理实体实例并将这些更改持久保存到数据库   使用Microsoft.EntityFrameworkCore.DbContext.SaveChanges。

很显然,这不是只读方案,并且运行此方法的唯一原因是尝试更新数据库中的实体。

是否有解释为什么此代码似乎与AsNoTracking摘要中给出的建议背道而驰?

1 个答案:

答案 0 :(得分:2)

在获取AsNoTracking()实例时使用Contact的事实也是将联系人context设置为{{ 1}}-由于State未跟踪EntityState.Modified,因此您需要明确地让contact知道此实体已被修改。

如果未使用context,则不需要。

NoTracking Queries(微软文档)

通常,在只读情况下(CRUD的R部分),您将从context中受益

对于在代码段中使用AsNoTracking()的潜在意图,@ Panagiotis Kanavos的comment是恕我直言:

  

“我想我理解这里的“聪明”之处-如果未授权更新,则加载联系人时不会进行跟踪以减少开销。如果是,则重新附加对象并尝试批准。根据状态,其最终状态将更新并最终保存。”