更新數據
數據庫中有主鍵所對應的記錄,修改實體到 Modified 狀態,調用 SaveChanges 時,生成 Update 語句。
更新已跟蹤實體的數據
當實體由 DbContext 獲取,且默認為已為跟蹤狀態,當我們改變實體的屬性值時,跟蹤器將自動將實體的狀態修改為 Modified 狀態。
var blog = context.Blogs.First(); blog.Url = "www.xcode.me"; context.SaveChanges();
更新未跟蹤實體的數據
對於未被跟蹤的斷開實體,可通過以下三種方案更新數據。
方案一:顯式設置 EntityState 狀態
context.Entry(blog).State = EntityState.Modified; context.SaveChanges();
方案二:在DbContext 或DbSet 上使用Update 方法
context.Update(blog); context.SaveChanges();
Update 方法 與 設置 EntityState 方案一樣,會將實體狀態設置為 Modified 狀態。由於跟蹤器沒有任何方法來識別哪些屬性值已經更改,所以生成的 UPDATE 語句會更新所有字段屬性。
Update 方法與顯示設置設置 EntityState 不同的是,Update 方法會修改相關實體(如 Blog 的 Posts 導航屬 性)的狀態為已修改,從而會為每個實體生成 UPDATE 語句。如果相關實體沒有對應的鍵值,就會標記為 Added 狀態,生成一條 Insert 語句。
方案三:在DbContext 或DbSet 上使用Attach 方法,然后遍歷對象圖,設置各個屬性的狀態。
當在已設置鍵值的實體上使用Attach 方法時,它的狀態將被設置為Unchanged 未修改狀態,這將導致根本不會生成任何 SQL 語句。
當在沒有鍵值的實體上使用 Attach 方法時,一個 Detached 游離狀態的實體將被標記為 Added 已添加狀態。
context.Entry(entity).IsKeySet
不管怎么說,調用 Attach 方法后,該實體將被跟蹤器跟蹤,我們可以通知跟蹤器哪些屬性被修改,生成正確的
UPDATE 語句,而不是更新所有字段,這也許會獲得更好的性能。
var blog = new Blog { BlodId=1, Name="ZEROBLOG", Url = "www.xcode.me", Posts = new List<Post> { new Post { Title = "Intro to C#" }, new Post { Title = "Intro to VB.NET" }, new Post { Title = "Intro to F#" } } } _context.Attach(blog); _context.Entry(blog).Property("Name").IsModified = true; _context.SaveChanges();
以上代碼,生成的 UPDATE 語句只會更新 Name 屬性。
如果實體不使用自動生成的鍵,則應用程序必須確定是應插入實體還是應更新實體:
public static void InsertOrUpdate(BloggingContext context, Blog blog) { var existingBlog = context.Blogs.Find(blog.BlogId); if (existingBlog == null) { context.Add(blog); } else { context.Entry(existingBlog).CurrentValues.SetValues(blog); } context.SaveChanges(); }
TrackGraph 跟蹤對象圖
在內部,Add、Attach 和 Update 使用圖形遍歷,為每個實體就是否應將其標記為 Added(若要插
入)、Modified(若要更新)、Unchanged(不執行任何操作)或 Deleted(若要刪除)作出決定。 此機制是通過 TrackGraph API 公開的。
TrackGraph API 提供了對對象圖中各個實體的訪問,並允許您對每個實體分別執行定制代碼。這在處理這種由不同對象的相關實體的復雜對象圖的場景中非常有用。下面的示例復制了一個場景,其中對象圖是在Context之外構造的。
var blog = new Blog { BlogId = 1, Name = "zerodo", Url = "www.xcode.me", Posts = new List<Post> { new Post { PostId=1, Title = "Intro to C#",Content="AAA" }, new Post { PostId=2, Title = "Intro to VB.NET",Content="BBB" }, new Post { PostId=3, Title = "Intro to F#" ,Content="CCC"} } }; context.ChangeTracker.TrackGraph(blog, e => { if (e.Entry.Entity is Blog) { e.Entry.State = EntityState.Unchanged; } if (e.Entry.Entity is Post) { e.Entry.State = EntityState.Unchanged; context.Entry(e.Entry.Entity as Post) .Property("Title").IsModified = true; } }); context.SaveChanges();
以上示例,無論如何修改 Blog 或者 Post 的屬性值,只有 Post 的 Title 字段會被更新。
更改關系
var blog = new Blog { Name = "zeroblog", Url = "www.xcode.me" }; var post = context.Posts.First(); post.Blog = blog; context.SaveChanges();
更改關系:可設置導航屬性(不存在則創建),也可設置外鍵的值。