エンティティを更新しようとしていますが、次のエラーが発生しました。
InvalidOperationException:エンティティタイプ「BookLoan」のインスタンスは追跡できません。同じキーを持つこのタイプの別のインスタンスがすでに追跡されているためです。新しいエンティティを追加するとき、ほとんどのキータイプでは、キーが設定されていない場合(つまり、キープロパティにそのタイプのデフォルト値が割り当てられている場合)に、一意の一時キー値が作成されます。新しいエンティティのキー値を明示的に設定する場合は、既存のエンティティや他の新しいエンティティに対して生成された一時的な値と衝突しないようにしてください。既存のエンティティをアタッチするときは、特定のキー値を持つ1つのエンティティインスタンスのみがコンテキストにアタッチされるようにしてください。
少し調べましたが、_context.Update(bookloan);
を使用すると、すでに追跡されているエンティティを追跡しようとしているようですが、どうすればよいかわかりません。
私がやろうとしていることは、データベース内の既存のエンティティ/レコードを更新することです。他に何を共有するかわからないので、ここにgetおよびpostコントローラがあります。
Get
[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");
}
....
_
補足:ビューを返すとき、return View(model);
を使用してモデルを返すことをお勧めします-フォームコントロールは、そうでない場合でも(ModelState
から値を取得するため)正しく設定されますが、モデルプロパティへの参照(例:_<div>@Model.someProperty</div>
_)があると、例外がスローされます。