在日常使用Entity Framework中,數據更新通常會用到。下麵就簡單封裝了一個DBContext類 public partial class EFContext<T> : DbContext where T : class { public EFContext(): base("name=M ...
在日常使用Entity Framework中,數據更新通常會用到。下麵就簡單封裝了一個DBContext類
public partial class EFContext<T> : DbContext where T : class { public EFContext(): base("name=MyConnectionString") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { Database.SetInitializer<EFContext<T>> (null); modelBuilder.Configurations.Add(new MemberMap()); modelBuilder.Configurations.Add(new RoleMap()); base.OnModelCreating(modelBuilder); } public DbSet<T> Table { get; set; } public IQueryable<T> GetList(Expression<Func<T,bool>> where) { return this.Table.Where(where); } public void Update(T entity) { if (entity == null) { throw new ArgumentException("entity"); } this.SaveChanges(); } }View Code
第一種更新方式,先通過Entity Framework從資料庫中查找出一條記錄(實體對象),然後修改實體對象的各個屬性,最後調用Update方法
static void Main(string[] args) { EFContext<Member> memberContext = new EFContext<Member>(); var members = memberContext.GetList(m => true).ToList(); var model = members.Find(m => m.Id == 3); //第一種更新方式 model.Name = "豬八戒"; model.Delete = false; memberContext.Update(model); Console.ReadKey(); }
運行程式前:
運行程式後:
上面的方式可以修改為下麵方式,DbContext封裝類中Update可以修改為如下的形式:
public void Update(T entity) { if (entity == null) { throw new ArgumentException("entity"); } this.Table.Attach(entity); this.Entry(entity).State = EntityState.Modified; this.SaveChanges(); }
static void Main(string[] args) { EFContext<Member> memberContext = new EFContext<Member>(); var members = memberContext.GetList(m => true).ToList(); var model = members.Find(m => m.Id == 3); //第一種更新方式 model.Name = "沙師弟"; model.Delete = true; memberContext.Update(model); Console.ReadKey(); }
運行前:
運行後:
第二種方式是new一個對象,這個對象各個屬性賦值,主鍵Id與資料庫某條已存在的記錄的Id相同
static void Main(string[] args) { EFContext<Member> memberContext = new EFContext<Member>(); var members = memberContext.GetList(m => true).ToList(); //var model = members.Find(m => m.Id == 3); ////第一種更新方式 //model.Name = "沙師弟"; //model.Delete = true; //memberContext.Update(model); //第二種方式 Member entity = new Member(); entity.Id = 3; entity.Name = "李小龍"; entity.Password = "lixiaolong"; entity.Delete = false; entity.RoleId = 3; memberContext.Update(entity); Console.WriteLine("update complete."); Console.ReadKey(); }
運行程式,會拋出異常。
附加類型“Core.Member”的實體失敗,因為相同類型的其他實體已具有相同的主鍵值。在使用 "Attach" 方法或者將實體的狀態設置為 "Unchanged" 或 "Modified" 時如果圖形中的任何實體具有衝突鍵值,則可能會發生上述行為。這可能是因為某些實體是新的並且尚未接收資料庫生成的鍵值。在此情況下,使用 "Add" 方法或者 "Added" 實體狀態跟蹤該圖形,然後將非新實體的狀態相應設置為 "Unchanged" 或 "Modified"。
因為Attach的實體對象是通過new創建的,而不是通過Entity Framework從資料庫中獲取的,但實例的主鍵對應數據在資料庫中存在,該實例而不存在於DBContext上下文中,嘗試Attach會拋出異常。通過監視可以看到是未附加到DbContext中
修改Update方法如下:
public void Update(T entity) { if (entity == null) { throw new ArgumentException("entity"); } if (this.Entry(entity).State == EntityState.Detached) { HandleDetached(entity); } this.Table.Attach(entity); this.Entry(entity).State = EntityState.Modified; this.SaveChanges(); } private bool HandleDetached(T entity) { var objectContext = ((IObjectContextAdapter)this).ObjectContext; var entitySet = objectContext.CreateObjectSet<T>(); var entityKey = objectContext.CreateEntityKey(entitySet.EntitySet.Name, entity); object foundSet; bool exists = objectContext.TryGetObjectByKey(entityKey, out foundSet); if (exists) { objectContext.Detach(foundSet); //從上下文中移除 } return exists; }
再次運行程式,沒有問題