我正在尝试更新一个实体,但遇到了以下错误:
InvalidOperationException: The instance of entity type 'BookLoan' cannot be tracked because another instance of this type with the same key is already being tracked. When adding new entities, for most key types a unique temporary key value will be created if no key is set (i.e. if the key property is assigned the default value for its type). If you are explicitly setting key values for new entities, ensure they do not collide with existing entities or temporary values generated for other new entities. When attaching existing entities, ensure that only one entity instance with a given key value is attached to the context.
我做了一些研究,据我所知,当我使用 _context.Update(bookloan);
时,我显然是在尝试跟踪一个已经被跟踪的实体,但我并不是真的确定要做什么。
我想做的是更新数据库中的现有实体/记录。这是 get 和 post Controller ,因为我不确定还有什么要分享。
获取
[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();
}
最佳答案
您的上下文已经包含该实体,因此与其创建一个新实体,不如根据该实体的 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");
}
....
旁注:返回 View 时,最好使用 return View(model);
传回模型- 即使您不这样做,您的表单控件也会被正确填充(因为它们从 ModelState
获取值),但是如果您有任何对模型属性的引用(例如 <div>@Model.someProperty</div>
),它会抛出异常。
关于c# - 无法跟踪实体类型 'BookLoan' 的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40198433/