实体类型'BookLoan'无法被追踪

本文关键字:追踪 实体 BookLoan 类型 | 更新日期: 2023-09-27 18:14:18

我正在尝试更新一个实体,我遇到了以下错误:

InvalidOperationException:实体类型'BookLoan'的实例无法跟踪,因为此类型的另一个实例具有相同的钥匙已经被追踪了。在添加新实体时,对于大多数键如果没有设置键,将创建唯一的临时键值(例如,如果key属性被分配为其类型的默认值)。如果您显式地为新实体设置键值,请确保它们是否与现有实体或生成的临时值发生冲突对于其他新实体。在附加现有实体时,请确保类中只附加一个具有给定键值的实体实例上下文。

我做了一点研究,从我可以告诉我显然试图跟踪一个已经跟踪的实体,当我使用_context.Update(bookloan);,但我不确定该怎么做。

我要做的是更新我的数据库中现有的实体/记录。这里是get和post控制器,因为我不确定还有什么可以分享的。

得到

    [HttpGet]
    public async Task<IActionResult> Return(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }
        if (isBookCheckedOut(id) == false)
        {
            //Not checked out
            return RedirectToAction("Index");
        }
        else
        {
            var bookloan = (from book in _context.Books.Where(b => b.BookId == id)
                        join loan in _context.BookLoans.Where(x => !x.ReturnedOn.HasValue) on book.BookId equals loan.BookID into result
                        from loanWithDefault in result.DefaultIfEmpty()
                        select new BookReturnViewModel
                        {
                            BookLoanID = loanWithDefault.BookLoanID,
                            BookID = book.BookId,
                            Title = book.Title,
                            StudentID = loanWithDefault == null ? null : loanWithDefault.StudentID,
                            StudentFristName = loanWithDefault == null ? null : loanWithDefault.Student.FirstName,
                            StudentLastName = loanWithDefault == null ? null : loanWithDefault.Student.LastName,
                            //Fines
                            CheckedOutOn = loanWithDefault == null ? (DateTime?)null : loanWithDefault.CheckedOutOn,
                            IsAvailable = loanWithDefault == null,
                            AvailableOn = loanWithDefault == null ? (DateTime?)null : loanWithDefault.DueOn
                        }).FirstOrDefault();
            if (bookloan == null)
            {
                return NotFound();
            }
            return View(bookloan);
        }
    }

:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Return(BookReturnViewModel model)
    {

        if (ModelState.IsValid && isBookCheckedOut(1) == true)
        {
            var bookloan = new BookLoan()
            {
                BookLoanID = model.BookLoanID,
                BookID = model.BookID,
                StudentID = model.StudentID,
                CheckedOutOn = (DateTime)model.CheckedOutOn,
                DueOn = (DateTime)model.AvailableOn,
                ReturnedOn = DateTime.Now
            };

            try
            {
                _context.Update(bookloan);
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
            }
            return RedirectToAction("Index");
        }
        else
        {
        }
        return View();
    }

实体类型'BookLoan'无法被追踪

您的上下文已经包含了实体,所以与其创建一个新的实体,不如根据实体的ID获取现有的实体并更新其属性,然后保存它

if (ModelState.IsValid && isBookCheckedOut(1) == true)
{
    // Get the existing entity
    BookLoan bookLoan = db.BookLoans.Where(x => x.BookLoanID == model.BookLoanID).FirstOrDefault();
    if (bookLoan != null)
    {
        bookLoan.BookID = model.BookID;
        bookLoan.StudentID = model.StudentID;
        .... // update other properties as required
        _context.Update(bookloan);
        await _context.SaveChangesAsync();
        return RedirectToAction("Index");
    }
    ....

旁注:当返回视图时,它的良好做法是使用return View(model);传递回模型-你的表单控件将被正确填充,即使你不(因为他们从ModelState的值),但如果你有任何引用模型属性(例如<div>@Model.someProperty</div>)它会抛出一个异常。