Comment mettre à jour l’enregistrement en utilisant Entity Framework 6?

J’essaie de mettre à jour l’enregistrement en utilisant EF6. D’abord, trouver l’enregistrement, s’il existe, le mettre à jour. Voici mon code: –

var book = new Model.Book { BookNumber = _book.BookNumber, BookName = _book.BookName, BookTitle = _book.BookTitle, }; using (var db = new MyContextDB()) { var result = db.Books.SingleOrDefault(b => b.BookNumber == bookNumber); if (result != null) { try { db.Books.Attach(book); db.Entry(book).State = EntityState.Modified; db.SaveChanges(); } catch (Exception ex) { throw; } } } 

Chaque fois que j’essaie de mettre à jour l’enregistrement en utilisant le code ci-dessus, je reçois cette erreur: –

{System.Data.Entity.Infrastructure.DbUpdateConcurrencyException: l’instruction de mise à jour, d’insertion ou de suppression du magasin a affecté un nombre inattendu de lignes (0). Les entités peuvent avoir été modifiées ou supprimées depuis le chargement des entités. Actualiser ObjectStateManager ensortinge

Vous essayez de mettre à jour l’enregistrement (ce qui signifie pour moi “modifier une valeur sur un enregistrement existant et le sauvegarder”). Vous devez donc récupérer l’object, apporter une modification et l’enregistrer.

 using (var db = new MyContextDB()) { var result = db.Books.SingleOrDefault(b => b.BookNumber == bookNumber); if (result != null) { result.SomeValue = "Some new value"; db.SaveChanges(); } } 

J’ai passé en revue le code source d’Entity Framework et trouvé un moyen de mettre à jour une entité si vous connaissez la propriété Key. Dans d’autres cas, vous devez vérifier l’implémentation de AddOrUpdate:

 public void Update(T item) where T: Entity { // assume Entity base class have an Id property for all items var entity = _collection.Find(item.Id); if (entity == null) { return; } _context.Entry(entity).CurrentValues.SetValues(item); } 

J’espère que cette aide!

Vous pouvez utiliser la méthode AddOrUpdate :

 db.Books.AddOrUpdate(book); //requires using System.Data.Entity.Migrations; db.SaveChanges(); 

Vous avez donc une entité qui est mise à jour et que vous souhaitez mettre à jour dans la firebase database avec le moins de code possible. La concurrence est toujours délicate, mais je suppose que vous voulez simplement que vos mises à jour soient gagnantes. Voici comment je l’ai fait pour mon cas et modifié les noms pour imiter vos classes. IOW, juste changer d’attacher à append, et ça marche pour moi:

 public static void SaveBook(Model.Book myBook) { using (var ctx = new BookDBContext()) { ctx.Books.Add(myBook); ctx.Entry(myBook).State = System.Data.Entity.EntityState.Modified; ctx.SaveChanges(); } } 

Ce code est le résultat d’un test pour mettre à jour uniquement un ensemble de colonnes sans faire une requête pour renvoyer d’abord l’enregistrement. Il utilise d’abord le code EF 7.

 //The function receives an object type to receive a custom object can be a view model or an anonymous object wit the properties you will like to change. This is part of a repository for a Contacts object. public int Update(object entity) { var entityProperties = entity.GetType().GetProperties(); Contacts con = ToType(entity, typeof(Contacts)) as Contacts; if (con != null) { _context.Entry(con).State = EntityState.Modified; _context.Contacts.Attach(con); foreach (var ep in entityProperties) { //Here is checking if the property is named Id dont add it in the update. It can be refactored to look in the annotations to find a key or to fin in the name any part named id if(ep.Name != "Id") _context.Entry(con).Property(ep.Name).IsModified = true; } } return _context.SaveChanges(); } public static object ToType( object obj, T type) { //create instance of T type object: object tmp = Activator.CreateInstance(Type.GetType(type.ToSsortingng())); //loop through the properties of the object you want to covert: foreach (PropertyInfo pi in obj.GetType().GetProperties()) { try { //get the value of property and try to assign it to the property of T type object: tmp.GetType().GetProperty(pi.Name).SetValue(tmp, pi.GetValue(obj, null), null); } catch (Exception ex) { // Logging.Log.Error(ex); } } //return the T type object: return tmp; } 

Voici le code complet:

  public interface IContactRepository { IEnumerable GetAllContats(); IEnumerable GetAllContactsWithAddress(); int Update(object c); } public class ContactRepository : IContactRepository { private ContactContext _context; public ContactRepository(ContactContext context) { _context = context; } public IEnumerable GetAllContats() { return _context.Contacts.OrderBy(c => c.FirstName).ToList(); } public IEnumerable GetAllContactsWithAddress() { return _context.Contacts .Include(c => c.Address) .OrderBy(c => c.FirstName).ToList(); } //TODO Cambiar properties a lambda expression public int Update(object entity) { var entityProperties = entity.GetType().GetProperties(); Contacts con = ToType(entity, typeof(Contacts)) as Contacts; if (con != null) { _context.Entry(con).State = EntityState.Modified; _context.Contacts.Attach(con); foreach (var ep in entityProperties) { if(ep.Name != "Id") _context.Entry(con).Property(ep.Name).IsModified = true; } } return _context.SaveChanges(); } public static object ToType( object obj, T type) { //create instance of T type object: object tmp = Activator.CreateInstance(Type.GetType(type.ToSsortingng())); //loop through the properties of the object you want to covert: foreach (PropertyInfo pi in obj.GetType().GetProperties()) { try { //get the value of property and try to assign it to the property of T type object: tmp.GetType().GetProperty(pi.Name).SetValue(tmp, pi.GetValue(obj, null), null); } catch (Exception ex) { // Logging.Log.Error(ex); } } //return the T type object: return tmp; } } public class Contacts { public int Id { get; set; } public ssortingng FirstName { get; set; } public ssortingng LastName { get; set; } public ssortingng Email { get; set; } public ssortingng Company { get; set; } public ssortingng Title { get; set; } public Addresses Address { get; set; } } public class Addresses { [Key] public int Id { get; set; } public ssortingng AddressType { get; set; } public ssortingng StreetAddress { get; set; } public ssortingng City { get; set; } public State State { get; set; } public ssortingng PostalCode { get; set; } } public class ContactContext : DbContext { public DbSet Address { get; set; } public DbSet Contacts { get; set; } public DbSet States { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { var connSsortingng = "Server=YourServer;Database=ContactsDb;Trusted_Connection=True;MultipleActiveResultSets=true;"; optionsBuilder.UseSqlServer(connSsortingng); base.OnConfiguring(optionsBuilder); } } 

Voici la meilleure solution à ce problème: Dans View, ajoutez tous les ID (clés). Envisagez de nommer plusieurs tables (First, Second and Third)

 @Html.HiddenFor(model=>model.FirstID) @Html.HiddenFor(model=>model.SecondID) @Html.HiddenFor(model=>model.Second.SecondID) @Html.HiddenFor(model=>model.Second.ThirdID) @Html.HiddenFor(model=>model.Second.Third.ThirdID) 

En code C #,

 [HttpPost] public ActionResult Edit(First first) { if (ModelState.Isvalid) { if (first.FirstID > 0) { datacontext.Entry(first).State = EntityState.Modified; datacontext.Entry(first.Second).State = EntityState.Modified; datacontext.Entry(first.Second.Third).State = EntityState.Modified; } else { datacontext.First.Add(first); } datacontext.SaveChanges(); Return RedirectToAction("Index"); } return View(first); } 

Vous devriez utiliser le. Méthode Entry () si vous souhaitez mettre à jour tous les champs de votre object. Gardez également à l’esprit que vous ne pouvez pas modifier le champ id (clé), par conséquent, commencez par définir l’ID à certains lorsque vous éditez.

 using(var context = new ...()) { var EditedObj = context .Obj .Where(x => x. ....) .First(); NewObj.Id = EditedObj.Id; //This is important when we first create an object (NewObj), in which the default Id = 0. We can not change an existing key. context.Entry(EditedObj).CurrentValues.SetValues(NewObj); context.SaveChanges(); } 

Vous devriez supprimer db.Books.Attach(book);

 using(var myDb = new MyDbEntities()) { user user = new user(); user.username = "me"; user.email = "[email protected]"; myDb.Users.Add(user); myDb.users.Attach(user); myDb.Entry(user).State = EntityState.Modified;//this is for modiying/update existing entry myDb.SaveChanges(); } 

Voici ma méthode de mise à jour d’entité post-RIA (pour la période Ef6):

 public static void UpdateSegment(ISegment data) { if (data == null) throw new ArgumentNullException("The expected Segment data is not here."); var context = GetContext(); var originalData = context.Segments.SingleOrDefault(i => i.SegmentId == data.SegmentId); if (originalData == null) throw new NullReferenceException("The expected original Segment data is not here."); FrameworkTypeUtility.SetProperties(data, originalData); context.SaveChanges(); } 

Notez que FrameworkTypeUtility.SetProperties() est une fonction utilitaire minuscule que j’ai écrite longtemps avant AutoMapper sur NuGet:

 public static void SetProperties(TIn input, TOut output, ICollection includedProperties) where TIn : class where TOut : class { if ((input == null) || (output == null)) return; Type inType = input.GetType(); Type outType = output.GetType(); foreach (PropertyInfo info in inType.GetProperties()) { PropertyInfo outfo = ((info != null) && info.CanRead) ? outType.GetProperty(info.Name, info.PropertyType) : null; if (outfo != null && outfo.CanWrite && (outfo.PropertyType.Equals(info.PropertyType))) { if ((includedProperties != null) && includedProperties.Contains(info.Name)) outfo.SetValue(output, info.GetValue(input, null), null); else if (includedProperties == null) outfo.SetValue(output, info.GetValue(input, null), null); } } } 

Comme dit Renat, enlevez: db.Books.Attach(book);

Modifiez également votre requête de résultat pour utiliser “AsNoTracking”, car cette requête rejette l’état du modèle de la structure d’entité. Il pense que “résultat” est le livre à suivre maintenant et vous ne le voulez pas.

 var result = db.Books.AsNoTracking().SingleOrDefault(b => b.BookNumber == bookNumber); 

Essayez-le ….

UpdateModel (livre);

 var book = new Model.Book { BookNumber = _book.BookNumber, BookName = _book.BookName, BookTitle = _book.BookTitle, }; using (var db = new MyContextDB()) { var result = db.Books.SingleOrDefault(b => b.BookNumber == bookNumber); if (result != null) { try { UpdateModel(book); db.Books.Attach(book); db.Entry(book).State = EntityState.Modified; db.SaveChanges(); } catch (Exception ex) { throw; } } } 

J’ai trouvé un moyen qui fonctionne très bien.

  var Update = context.UpdateTables.Find(id); Update.Title = title; // Mark as Changed context.Entry(Update).State = System.Data.Entity.EntityState.Modified; context.SaveChanges();