J'utilise Identity Core 1.0 avec ASP.NET MVC Core 1.0 et Entity Framework Core 1.0 pour créer un système d'enregistrement d'utilisateur simple avec cet article comme point de départ, et j'essaie d'ajouter des rôles d'utilisateur. Je peux ajouter des rôles d'utilisateur, mais je ne peux pas les modifier. Voici l'action Edit
dans la RolesController
:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(IdentityRole role)
{
try
{
_db.Roles.Attach(role);
_db.Entry(role).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("Index");
}
catch (Exception ex)
{
Console.WriteLine(ex);
return View();
}
}
Voici le formulaire dans la vue correspondante:
@model Microsoft.AspNet.Identity.EntityFramework.IdentityRole
@{
ViewBag.Title = "Edit";
}
<h2>Edit Role</h2>
<hr />
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.Id)
<div>Role name</div>
<p>@Html.TextBoxFor(model => model.Name)</p>
<input type="submit" value="Save" />
}
Le nouveau nom de rôle n'enregistre pas dans la base de données et j'obtiens l'exception suivante: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded.
J'ai pu utiliser ce code exact (avec la dépendance Microsoft.AspNet.Identity.EntityFramework
au lieu de EntityFrameworkCore
) pour modifier les entrées de base de données à l'aide de EF 7, Identity 3, etc.
Pourquoi ce code ne permet-il pas de modifier les entrées de la base de données?
À moins d'une exception cachée qui se cache derrière cela en tant qu'exception aléatoire stupide, la raison est clairement indiquée dans l'exception.
Vérifiez la Id
sur l'objet role
au fur et à mesure que vous le recevez pour votre action Edit
et essayez de rechercher cet identifiant dans la base de données. Le message d'exception que vous voyez indique qu'il s'attend à trouver une ligne avec un ID correspondant à l'objet que vous avez attaché, mais ce n'est pas le cas. La mise à jour échoue, car il n'a pas pu localiser une ligne correspondante pour la mettre à jour. .
EDIT:
Vous attachez l'entité deux fois, supprimez l'appel à .Attach(role)
et laissez la ligne en dessous de celle-ci, ce qui est suffisant pour ajouter l'objet au contexte de suivi dans un état modifié.
//_db.Roles.Attach(role); //REMOVE THIS LINE !.
_db.Entry(role).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
Attention, le fait de définir l'état de l'entrée sur modifié mettra à jour toutes les valeurs de propriété lors de l'appel de .SaveChanges()
. Par conséquent, si vous souhaitez mettre à jour uniquement certaines propriétés, reportez-vous à this answer .
Si cela ne résout pas votre problème, vérifiez les exceptions internes que vous avez peut-être manquées. Parfois, les messages d'exception n'ont pas de sens et masquent le problème réel que vous pourriez éventuellement trouver dans l'exception interne.
Vous pouvez essayer comme indiqué ci-dessous.
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(IdentityRole role)
{
try
{
_db.Entry(role).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("Index");
}
catch (Exception ex)
{
Console.WriteLine(ex);
return View();
}
}
Remarque :
Quand _db.Entry(role).State = EntityState.Modified;
_db
, vous marquez également l'entité comme étant dirty
._db.SaveChanges()
, EF générera une instruction update
Qui will update all the fields of the entity
. Quand _db.Roles.Attach(role)
_db.Entry(role).State = EntityState.Unchanged;
.update a property on the entity
, la prochaine fois que vous appelez context.SaveChanges()
, EF
ne générera pas a database update
pour cette entity
.i.e. Si vous devez générer une mise à jour de la base de données, procédez comme suit:
_db.Roles.Attach(role); // State = Unchanged
role.RoleName = "Admin"; // State = Modified, and only the RoleName property is dirty
context.SaveChanges();
Vos réponses ne fonctionnent pas pour moi. Et j'ai résolu mon erreur comme ceci. Modification des propriétés de la classe Model
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public string Id { get; set; }
après avoir changé ma classe de mapping
builder.Property(c => c.Id).HasColumnName("ID").IsRequired();
Le dernier changement est
CustomerEntity thisrole = (from x in db.Customers
where x.Id == Id
select x).First();
thisrole.Id = accountNum;
thisrole.Name = name;
thisrole.Phone = phone;
thisrole.Email = email;
thisrole.Address = address;
db.SaveChanges();
return true;
J'espère que cette solution fonctionne pour quelqu'un.
Si vous avez un déclencheur INSTEAD OF INSERT sur la table, la base de données annule l'opération et EntityFramework déclenche cette erreur.
J'ai résolu ce problème en combinant les deux méthodes
var thisRole = _db.Roles.Where(r => r.Id.Equals(role.Id,
StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
_db.Roles.Attach(thisRole);
thisRole.Name = role.Name;
_db.SaveChanges();