EF原理
EF 會自動把 Where()、OrderBy()、Select()等這些編譯成“表達式樹(Expression Tree)”,然后會把表達式樹翻譯成 SQL 語句去執行。(編譯原理,AST)因此不是“把數據都取到內存中,然后使用集合的方法進行數據過濾”,因此性能不會低。但是如果這個操作不能被翻譯成 SQL 語句,則或者報錯,或者被放到內存中操作,性能就會非常低
跟蹤EF的查詢Sql語句:
DbContext 有一個 Database 屬性,其中的 Log 屬性,是 Action<String>委托類型,也就是可以指向一個 void A(string s)方法,其中的參數就是執行的 SQL 語句,每次 EF 執行 SQL 語句的時候都會執行 Log。因此就可以知道執行了什么 SQL。
執行原始sql語句
執行非查詢語句,調用 DbContext 的 Database 屬性的 ExecuteSqlCommand 方法,可以通過占位符的方式傳遞參數:
更新語句
ctx.Database.ExecuteSqlCommand("update T_Persons set Name={0},CreateDateTime=GetDate()","zjf");
占位符的方式不是字符串拼接,經過觀察生成的 SQL 語句,發現仍然是參數化查詢,因此不會有 SQL 注入漏洞。
查詢語句:
var q1 = ctx.Database.SqlQuery<Item1>("select Name,Count(*) Count from T_Persons where Id>{0} and CreateDateTime<={1} group by Name"
返回值是 DbRawSqlQuery<T> 類型,也是實現了 IEnumerable 接口
類似於 ExecuteScalar 的操作比較麻煩:
int c = ctx.Database.SqlQuery<int>("select count(*) from T_Persons").SingleOrDefault();
EF中的對象狀態:
Detached(游離態,脫離態)、Unchanged(未改變)、Added(新增)、Deleted(刪除)、Modified(被修改)。
轉換圖

Add()、Remove()修改對象的狀態。所有狀態之間幾乎都可以通過: Entry(p).State=xxx 的方式 進行強制狀態轉換
EF 優化的一個技巧
如果查詢出來的對象 只是供顯示使用,不會修改、刪除后保存,那么可以使用AsNoTracking()來使得查詢出來的對象是 Detached 狀態,這樣對對象的修改也還是 Detached狀態,EF 不再跟蹤這個對象狀態的改變,能夠提升性能。
var p1 = ctx.Persons.Where(p => p.Name == "rupeng.com").FirstOrDefault(); Console.WriteLine(ctx.Entry(p1).State);
改成:
var p1 = ctx.Persons.AsNoTracking().Where(p => p.Name == "rupeng.com").FirstOrDefault(); Console.WriteLine(ctx.Entry(p1).State);
因為 AsNoTracking()是 DbQuery 類(DbSet 的父類)的方法,所以要先在 DbSet 后調用AsNoTracking()。
