EF(EntityFramework)性能優化與高級用法

1、使用AsNoTracking()

使用AsNoTracking()後,將不監聽對象的狀態(是否被改變);當確定查詢出來的數據不會改變的時候使用AsNoTracking();

使用context.Entry<User>(user).State 查看對象監聽狀態。

2、正確使用Find(id=10)來代替FirstOrDefault(t=>t.id=10)

Find會優先查詢緩存,當前面已經查詢過這條數據的時候使用,而FirstOrDefault每次都會查詢數據庫;

當id=10的數據被修改之後,find查出的數據是新數據。

3、正確使用延遲查詢(延遲加載)

使用延遲加載可以疊加多次查詢條件,一次性提交給數據庫,可以按需獲取數據。

3.1 使用ToList()的時候會立馬執行數據庫sql查詢,看到過很多同學先ToList()再Where()過濾。

        其它的還有:Count() 、FirstOrDefault()、迭代器foreach。等都會立刻執行sql。

3.2 迭代(如foreach)使用延遲查詢的時候,迭代完了才關閉鏈接,應當避免使用這種場景。可以在迭代之前ToList()。

3.3 延遲加載的對象(IQueryable<T>)脫離了DbContext上下文對象的範圍後不能被查詢,因爲DbContext被釋放了。

4、正確區分IQueryable和IEnumerable

4.1 IEnumerable(linq to object)用於操作內存對象。是個迭代器的實現。

       Where(t=>t.id>10)中的“t=>t.id>10”是個委託

4.2 IQueryable(linq to sql)用於操作數據庫,且繼承了IEnumerable。 IQueryable中實現了表達式目錄樹(Expression),IQueryProvider根據表達式目錄樹來構建sql語句。

       Where(t=>t.id>10)中的“t=>t.id>10”是個表達式目錄樹

5、正確使用導航屬性

在主表對象中包含一個子表集合對象的屬性就是導航屬性。跟數據庫中的主外鍵設置無關。

5.1 導航屬性要延遲加載必須具備兩個條件:

        a、導航屬性是virtual的;

        b、延遲查詢必須是開啓的。context.Configuration.LazyLoadingEnabled=true; (默認就是true的)

5.2  延遲查詢關閉之後可以使用顯示加載的方式:

      加載集合: context.Entry<Company>(company).Collection(t=>t.Users).Load();

      加載單個: context.Entry<Company>(company).Reference(t=>t.Users).Load();

6、預先加載

使用Include,查詢主表時把子表(導航屬性)也一次性查出來。延遲查詢關閉後也不影響的。

例如:context.Set<Company>().Include("Users").Where(t=>t.id<10);

7、使用TransactionScope

TransactionScope可以完成多個context多個SaveChange的事務問題,默認一個SaveChange是一個事務

TransactionScope可以用來做分佈式事務。

還可以使用context.Database.BeginTransaction做單庫事務。

using (DbContext context = new DbContext())
{
    using (TransactionScope tran = new TransactionScope())
    {
        context.SaveChange();
        context.SaveChange();
        //無異常會執行Complete 提交事務
        tran.Complete();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章