每個上下文實例都有一個 ChangeTracker,它負責跟蹤需要寫入數據庫的更改。 更改實體類的實例時,這些更改會記錄在 ChangeTracker 中,然后在調用 SaveChanges 時被寫入數據庫。 此數據庫提供程序負責將更改轉換為特定於數據庫的操作(例如,關系數據庫的 INSERT、UPDATE 和DELETE 命令)。
ChangeTracker
提供對上下文所有實體狀態的跟蹤信息。
EntityEntry
表示給定實體的跟蹤信息,可通過 ChangeTracker.Entries 、 DbContext.Entry 和 DbSet.Entry 獲取。
EntityState
被跟蹤實體的狀態
狀態演練
查詢一個對象,觀察跟蹤和未跟蹤情況下對象的狀態。
_context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; Blog blog = _context.Find<Blog>(1) ; EntityEntry entityEntry = _context.Entry(blog);
添加數據
添加數據是指:數據庫無記錄,添加新的記錄到數據庫。
DbContext.Add() 或 DbSet.Add()
開始跟蹤給定實體,將尚未被跟蹤的任何實體更改為已添加狀態。 Detached=>Added
更 多 重 載 :AddAsync 、 AddRange 和 AddRangeAsync
https://www.cnblogs.com/CreateMyself/p/9043744.html
DbContext.Attach() 或 DbSet.Attach()
開始在上下文中跟蹤給定的實體,將執行導航屬性的遞歸搜索以查找尚未被上下文跟蹤的可到達實體。
這些實體也將開始被上下文跟蹤。通俗點來講就是查找所有 Detached 游離狀態的對象圖,將其設置為被上下文跟蹤的狀態,跟蹤起來,跟蹤成何種狀態,有以下兩種情況
如果可訪問實體的主鍵值已設置,則將以“未更改”狀態跟蹤它。Detached=>Unchanged
如果未設置主鍵值,則將在 “已添加”狀態下跟蹤它。Detached=>Added
批處理此操作:AttachRange
Blog blog = new Blog() { Name = "zeroblog", Url = "www.xcode.me" }; EntityEntry entityEntry = _context.Entry(blog); Console.WriteLine(entityEntry.State); _context.Attach(blog); Console.WriteLine(entityEntry.State); _context.SaveChanges(); Console.WriteLine(entityEntry.State);
添加新實體的關系圖
var blog = new Blog { Name = "zerodo", 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.Blogs.Add(blog); //_context.Blogs.Attach(blog); _context.SaveChanges();
注意無法插入數據的情況
var blog = new Blog { Name = "zerodo", Url = "www.xcode.me", }; var posts = new List<Post> { new Post { Title = "Intro to C#",Blog=blog }, new Post { Title = "Intro to F#",Blog=blog } }; await _context.AddAsync(blog); await _context.SaveChangesAsync();
添加相關實體
var blog = _context.Blogs.Include(b => b.Posts).First(); var post = new Post { Title = "Intro to EF Core" }; blog.Posts.Add(post); _context.SaveChanges();
關於自增主鍵數據的強行插入
var blog1 = new Blog { BlogId = 33, Name = "zerodo1", Url = " www.xcode1.me", }; var blog2 = new Blog { BlogId = 44, Name = "zerodo2", Url = " www.xcode2.me", }; var blog3 = new Blog { BlogId = 55, Name = "zerodo3", Url = " www.xcode3.me", };
_context.Add(blog1); _context.Add(blog2); _context.Add(blog3); _context.Database.OpenConnection(); try { _context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [Blogs] ON"); await _context.SaveChangesAsync(); _context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [Blogs] OFF"); } finally { _context.Database.CloseConnection(); }
允許將顯式值插入到表的標識列中。
當多次調用插入數據時,最后執行 SaveChanges 保存時,將生成批處理語句,而不像之前版本的EF那樣,生成多條 SQL 語句,相比之下, EF Core 性能更高。
var blog1 = new Blog { Name = "zerodo1", Url = "www.xcode1.me", }; var blog2 = new Blog { Name = "zerodo2", Url = "www.xcode2.me", }; var blog3 = new Blog { Name = "zerodo3", Url = "www.xcode3.me", }; _context.Add(blog1); _context.Add(blog2); _context.Add(blog3); _context.SaveChanges();
What is Batching of Statement in Entity Framework Core?
使用存儲過程或者原生SQL保存數據
_context.Database.ExecuteSqlCommand("SQL");