[C#.NET][Entity Framework] 快取查詢與 DbEntityEntry.Reload
在使用EF操作資料庫時,可以利用快取機制 DbSet
在使用EF操作資料庫時,可以利用快取機制 DbSet<TEntity>.Local 來完成資料庫UI的操作,這要稍微瞭解追蹤與不追蹤查詢,才能使用的順手,在此將我的使用心得記錄一下
本文索引:
追蹤查詢,表示會將查詢結果存放至快取,快取有兩份
1.DbContext 的(DbEntityEntry<TEntity>),
2.DbSet<TEntity>.Local,若有查詢語法有調用Load方法,DbSet<TEntity>.Local 也會更新資料
調用追蹤查詢
1.利用 LINQ 語法來查詢資料庫實體,如下程式碼:
context.Posts.Load(); var find1 = this.dbContext.Products.FirstOrDefault(o => o.Id == 1);
2.利用 DbSet<EEntity>.SqlQuery查詢,如下程式碼:
var q2 = context.Products.SqlQuery("select * from products");
要注意的是,當 Database 已經修改資料,使用下列查循語法,仍會得到舊的資料,因為 this.dbContext.Products 裡面存放的仍是已被追蹤快取資料,
var find1 = this.dbContext.Products.FirstOrDefault(o => o.Id == 1);
DbSet<TEntity>.Local 資料繫結:
DbSet<TEntity>.Local 會回傳 ObservableCollection<T> 所以可以利用它輕易的完成資料繫結,第一次執行時可調用 DbSet<TEntity>.Load,這將會把查詢結果存放在 DbContext 的快取,並且更新 DbSet<TEntity>.Local,這時候的 Local 存放的是追蹤結果
- WPF 可直接繫結 Local
- WinForm 則是繫結 Local.ToBindingList
第一次繫結 Local.ToBindingList 就能拿到資料,如下圖:
private MyDbContext dbContext = new MyDbContext("localdb"); private void Form1_Load(object sender, EventArgs e) { this.dbContext.Products.Load(); this.dataGridView1.DataSource = this.dbContext.Products.Local.ToBindingList(); }
PS.它不會返回 EntityState.Deleted 實體
為了更新快取,我們可以調用 DbEntityEntry<TEntity>.Reload 方法從資料庫更新快取資料,如下程式碼:
var find1 = this.dbContext.Products.FirstOrDefault(o => o.Id == 1); this.dbContext.Entry(find1).Reload();若要用 Reload 處理大量資料,可以試著把 DbContext.Configuration.AutoDetectChangesEnabled=false,以便提昇程式執行效率;不過這樣的做法還是很慢,關閉 DbContext,放棄舊有的快取,重新讀取還比較快一些。
不追蹤查詢,表示回傳的實體將不會列入追蹤,我們也能得到新的實體資料,但這樣做不會更新快取資料,
有幾個查詢方法
AsNoTracking 查詢,如下程式碼:
var find1 = this.dbContext.Products.AsNoTracking().FirstOrDefault(o => o.Id == 1);
Database.SqlQuery 查詢,如下程式碼:
var q1 = context.Database.SqlQuery<Product>("select * from products");
文章出自:http://www.dotblogs.com.tw/yc421206/archive/2014/04/13/144718.aspx
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET