在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摘要中给出的建议背道而驰?
答案 0 :(得分:2)
在获取AsNoTracking()
实例时使用Contact
的事实也是将联系人context
设置为{{ 1}}-由于State
未跟踪EntityState.Modified
,因此您需要明确地让contact
知道此实体已被修改。
如果未使用context
,则不需要。
NoTracking Queries(微软文档)
通常,在只读情况下(CRUD的R部分),您将从context
中受益
对于在代码段中使用AsNoTracking()
的潜在意图,@ Panagiotis Kanavos的comment是恕我直言:
“我想我理解这里的“聪明”之处-如果未授权更新,则加载联系人时不会进行跟踪以减少开销。如果是,则重新附加对象并尝试批准。根据状态,其最终状态将更新并最终保存。”