如何使用entity framework6更新logging?

我正在尝试使用EF6更新logging。 首先findlogging,如果存在,则更新它。 这是我的代码:

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; } } } 

每次我尝试更新logging使用上面的代码,我得到这个错误: –

{System.Data.Entity.Infrastructure.DbUpdateConcurrencyException:存储更新,插入或删除语句影响意外数量的行(0)。 实体被加载后,实体可能已被修改或删除。 刷新ObjectStateManager的entrie

您正在尝试更新logging(对于我而言,“更改现有logging上的值并将其保存”)。 所以你需要检索对象,进行修改并保存。

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

我一直在审查entity framework的源代码,并find一种方法来实际更新实体,如果你知道Key属性,在其他情况下你需要检查AddOrUpdate实现:

 public void Update(T item) { var entity = _collection.Find(item.Id); if (entity == null) { return; } _context.Entry(entity).CurrentValues.SetValues(item); } 

希望这个帮助!

您可以使用AddOrUpdate方法:

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

此代码是testing的结果,只更新一组列而不进行查询以首先返回logging。 它首先使用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<T>( object obj, T type) { //create instance of T type object: object tmp = Activator.CreateInstance(Type.GetType(type.ToString())); //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 interface IContactRepository { IEnumerable<Contacts> GetAllContats(); IEnumerable<Contacts> GetAllContactsWithAddress(); int Update(object c); } public class ContactRepository : IContactRepository { private ContactContext _context; public ContactRepository(ContactContext context) { _context = context; } public IEnumerable<Contacts> GetAllContats() { return _context.Contacts.OrderBy(c => c.FirstName).ToList(); } public IEnumerable<Contacts> 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<T>( object obj, T type) { //create instance of T type object: object tmp = Activator.CreateInstance(Type.GetType(type.ToString())); //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 string FirstName { get; set; } public string LastName { get; set; } public string Email { get; set; } public string Company { get; set; } public string Title { get; set; } public Addresses Address { get; set; } } public class Addresses { [Key] public int Id { get; set; } public string AddressType { get; set; } public string StreetAddress { get; set; } public string City { get; set; } public State State { get; set; } public string PostalCode { get; set; } } public class ContactContext : DbContext { public DbSet<Addresses> Address { get; set; } public DbSet<Contacts> Contacts { get; set; } public DbSet<State> States { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { var connString = "Server=YourServer;Database=ContactsDb;Trusted_Connection=True;MultipleActiveResultSets=true;"; optionsBuilder.UseSqlServer(connString); base.OnConfiguring(optionsBuilder); } } 

所以你有一个更新的实体,并且你想用最less的代码在数据库中更新它…并发总是很棘手,但是我假设你只是想让你的更新获胜。 下面是我为了同样的情况做了这些,并修改了名字来模仿你的类。 IOW,只需改变附加添加,它适用于我:

 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(); } } 

你应该删除db.Books.Attach(book);

这是我的后RIA实体更新方法(对于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(); } 

请注意, FrameworkTypeUtility.SetProperties()是一个很小的实用函数,我在NuGet的AutoMapper之前写了很久:

 public static void SetProperties<TIn, TOut>(TIn input, TOut output, ICollection<string> 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); } } } 

这是对这个问题的最佳解决scheme:在视图中添加所有的ID(键)。 考虑有多个名为(第一,第二和第三)

 @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) 

在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); } 

像Renat说的,删除: db.Books.Attach(book);

此外,更改您的结果查询使用“AsNoTracking”,因为这个查询是抛出entity framework的模型状态。 它认为“结果”是现在跟踪的书,你不想这样做。

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

发布漂亮而简单的解决scheme 通过下面的链接来更新EntityFramework中的数据。

http://kerryritter.com/updating-or-replacing-entities-in-entity-framework-6/#comment-202