【问题标题】:ASP.NET Core - The instance of entity type cannot be trackedASP.NET Core - 无法跟踪实体类型的实例
【发布时间】:2018-08-07 04:21:06
【问题描述】:

我在尝试更新我的编辑操作中的上下文时遇到了一个问题:

[HttpPost]
public IActionResult Edit(Model.LeaveApplication leaveApplication) {

ViewBag.Title = "Edit Leave Application";
ViewBag.leavePeriodList = context.LeavePeriod.ToList();
ViewBag.LeaveTypeList = context.LeaveType.ToList();

try {    
    if (ModelState.IsValid) {    
        if (!validateDateRanges(leaveApplication, "edit")) {    
            return View(leaveApplication);
        }

        leaveApplication.NumDays = (float)CalculateNoOfDays(leaveApplication);
        context.LeaveApplication.Update(leaveApplication);
        context.SaveChanges();

        return RedirectToAction("Index");
    }    
}
catch (DbUpdateException) {    
    ModelState.AddModelError("", "Unable to edit leave application. " +
    "Please try again, and if the problem persists, " +
    "please see your system administrator.");
}              
    return View(leaveApplication);
}

我要做的是检查是否有超过 1 条记录以验证日期范围。如果只有 1 条记录,我将跳过验证并继续更新上下文。但是,我收到一条错误消息:

无法跟踪实体类型“LeaveApplication”的实例,因为已在跟踪具有相同键的该类型的另一个实例。

是什么导致了这个问题?

这是我的构造函数代码:

public class LeaveApplicationController : Controller {

    LeaveDBContext context;
    private readonly UserManager<ApplicationUser> userManager;
    private readonly SignInManager<ApplicationUser> signInManager;

    public LeaveApplicationController(LeaveDBContext context, UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager) {

        this.context = context;
        this.userManager = userManager;
        this.signInManager = signInManager;
    }
}

【问题讨论】:

  • 除了 上下文 之外还有其他 DbContext 实例吗?当我尝试通过两个上下文实例到达同一个实体对象时,它发生在我身上。如果这是问题所在,您应该使用单个上下文或在使用其他上下文到达它后取消跟踪
  • 不,我认为我没有任何其他 DbContext 实例,但我确实有一个 UserDbContext。在我的构造函数中,我包含了参数LeaveDbContextUserManager&lt;ApplicationUserSignInManager&lt;ApplicationUser&gt;
  • 你能发布你的构造函数代码吗?
  • @PavelLevchuk 好的,我已经更新了我的问题以包含构造函数代码
  • @iamhx,您可能使用 UserDbContext 访问同一实体。您可以通过分离实体来取消跟踪它; context.Entry(leaveApplication).State = EntityState.Detached;

标签: asp.net-mvc entity-framework asp.net-core


【解决方案1】:

您应该永远尝试保存通过帖子创建的对象。出现这种情况有许多安全原因,但您也偶然发现了一个基于 EF 工作方式的实用安全原因。

如果没有更多代码库,很难准确判断,但在某些时候,这个特定的 LeaveApplication 实例会加载到您的上下文中,然后开始跟踪它。当您尝试保存 不同 LeaveApplication 实例(即已发布的实例)时,EF 不能,因为它不是跟踪 那个 实例,而是已加载的实例早一点。

您应该做的是发布到视图模型类。然后,从您的上下文中直接拉出您要编辑的LeaveApplication 实例,并将视图模型中的数据映射到它上面。最后,保存该实例。然后,您将不再有任何问题,并且您可以获得防止过度发布黑客和其他发布后数据篡改的附带好处。此外,您的LeaveApplication id 应该是 URL 的一部分。 从不相信已发布的 ID。时期。由于 URL 中的 id 唯一标识资源,因此您可以轻松实现基于此的对象级权限。

【讨论】:

  • 谢谢,您的回答非常有用。我现在将继续将其更改为视图模型,并让您知道它是否有效!
  • 成功了!非常感谢!我以后一定会注意这一点的。
猜你喜欢
  • 2021-05-04
  • 2019-10-28
  • 1970-01-01
  • 2017-06-30
  • 2017-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-23
相关资源
最近更新 更多