I'm using .net core 6 and ef core 6. When I try to update(edit) an instance, it adds a new instance and not deleting the old one.
Inside of my Controller file:
//GET
public IActionResult Edit(int? id)
{
if (id == null || id == 0)
{
return NotFound();
}
var dbKitap = _db.Kitaplar.Find(id);
if (dbKitap == null)
{
return NotFound();
}
return View(dbKitap);
}
//POST
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(Kitap obj)
{
foreach (var kitap in _db.Kitaplar)
{
if (kitap.kitapAdi.Equals(obj.kitapAdi))
{
ModelState.AddModelError("kitapAdi", "Düzenlemek istediğiniz kitap zaten mevcuttur.");
}
}
if (ModelState.IsValid)
{
_db.Kitaplar.Update(obj);
_db.SaveChanges();
return RedirectToAction("Index");
}
return View(obj);
}
Inside of my Edit.cshtml file:
@model Kitap
<form method="post" asp-action="Edit">
<div class="border p-3 mt-4">
<h2 class="text-primary">Düzenle</h2>
<hr />
</div>
<div class="mb-3">
<label asp-for="kitapAdi"></label>
<input asp-for="kitapAdi" class="form-control" />
<span asp-validation-for="kitapAdi" class="text-danger"></span>
</div>
<div class="mb-3">
<label asp-for="kitapSirasi"></label>
<input asp-for="kitapSirasi" class="form-control" />
<span asp-validation-for="kitapSirasi" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary" style="width:150px">Düzenle</button>
<a asp-controller="Kitap" asp-action="Index" class="btn btn-secondary" style="width:150px">
Listeye Dön
</a>
</form>
Inside of my View.cshtml file(i'm putting the only part related to editing):
<div class="w-75 btn-group" role="group">
<a asp-controller="Kitap" asp-action="Edit" asp-route-id="@obj.kitapId"
class="btn btn-primary mx-2"> <i class="bi bi-pencil-square"></i>Düzenle</a>
</div>
My Model file:
using System.ComponentModel.DataAnnotations;
namespace Kitap_Web.Models
{
public class Kitap
{
[Key]
public int kitapId { get; set; }
[Required(ErrorMessage = "Gerekli alan.")]
public string kitapAdi { get; set; }
public int kitapSirasi { get; set; }
}
}
I tried adding @Html.HiddenFor(m => m.kitapId) to my Edit.cshtml file but then i'm running into "System.InvalidOperationException: 'The instance of entity type 'Kitap' cannot be tracked because another instance with the same key value for {'kitapId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.'" error.
I don't want to use SQL statements, if you can fix the problem without changing the structure of the project, it would be really good.
If you pass entity with id to your controller, then when iterating over dbset you are loading entities from database.
Those loaded entities are being tracked by EF change tracker, so when you are adding model passed from controller with existing Id - exception happens.
Either iterate using AsNoTracking() (_db.Kitaplar.AsNoTracking()
as far as I remember) and then append updated entity (append and set entity state to modified using change tracker) or extract entity from dbContext with the id of the model and modify its properties with values from model, excluding Id. Then save and it should work.