實體框架 (EF) 入門 => 六、性能注意事項


這個還真是復雜,看了看微軟的文檔,有些根本就看不懂,有些能看懂,但對我這種菜鳥也不會去用。

無從下手啊,前面放了幾個鏈接,挨個試試吧。

一、顯式打開連接

這個我測試過,有些時候,需要我們顯示打開連接,有時不用。

1、.SaveChanges()

沒寫錯吧,嘿嘿。

這個不需要關注連接的問題,因為不管之前你無論是修改、刪除、新增,只有一個SaveChanges(),一定是只用一個鏈接,並且系統還會自動使用事務。

2、查詢

增刪改一個SaveChanges()就搞定了,可查詢不是。

同時需要查詢多個數據的情況並不少見,比如EasyUI 的 DataGrid,它不僅要使用數據,還需要總行數,這時,就是兩個查詢,兩個查詢你雖然可以挨着寫,可實際情況卻是:

打開連接

查詢

關閉連接

打開連接

查詢

關閉連接

具體這樣影響多大性能不清楚,連接雖然在連接池中,但打開一次,應該是建立一次TCP連接,總要消耗一些性能。

針對這種情況,就可以顯示打開連接了:

使用using或try,畢竟涉及到連接了嗎,總要將它關閉,然后:

.Open()

查詢

查詢

.Close()或.Dis…()

二、延遲加載

不要使用延遲加載,要一次把需要的數據讀取出來。特別是在循環中使用延遲加載,每次都讀取一次數據庫,對性能影響非常大。

有主外鍵關系的使用.Include,沒有的使用.Join。

三、盡可能的使用.Select

記得以前學數據庫時,老師總是講,用什么字段select什么字段,我想,這里應該也是一樣,僅查詢需要的字段,查詢的字段少,在數據庫執行查詢時應該快一點,EF中應該也一樣吧,字段少需要賦值的東西就少,應該也會快。

至於select到新的實體類,還是到var,應該看復用程度和與其它功能(比如界面生成)的相關程度,如果僅用一次,var就很好。

當然,如果需要傳遞,就不能使用var,要使用 dynamic。

四、應用服務器查詢還是數據庫服務器查詢

直白點也就是先.ToList()還是后.ToList(),讓然這里只是舉例,只是想說明.ToList()才會到數據庫查詢,有些情況下並不需要.ToList()。

這個個人認為還是應該在數據庫服務器查詢,比較好規范開發人員行為,因為有些數據量比較大,你不能都查詢到應用服務器在select/where吧,這樣可能性能更差。如果你應用服務器比較空閑,可以移到數據庫中一個嗎。當然有些老的應用,架子搭在那了,就需要視情況而定了。

引用別人的文章來說明這個問題:

http://www.cnblogs.com/jake1/archive/2013/04/25/3043664.html

  1. 分頁的時候,盡量在數據庫里面去分頁.在我實際中的項目,我就發現我同事由於他不了解EF屬性,它的分頁都是做在內存中分頁.下面請看他的代碼.

         queryToList().Skip((pageInfo.PageIndex - 1) * pageInfo.PageSize).Take(pageInfo.PageSize);

         像上面的語句,他會先把數據從數據庫中查出來,然后才分頁.

          正確的寫法應如下:

       query.Skip((pageInfo.PageIndex - 1) * pageInfo.PageSize).Take(pageInfo.PageSize).ToList();這樣才會在數據庫中分頁.

上面這個示例非常典型,無論怎樣,分頁都應該在數據庫中,你把很多數據都讀取到應用服務器的內存中再取其中的10條記錄,真是有點小題大做了。

五、太復雜的查詢使用存儲過程

如果涉及多個表的關聯,最好使用存儲過程。EF雖然也能實現,但其生成的sql恐怕和預想的要差很遠。

六、主外鍵

能使用主外鍵的,盡可能的使用主外鍵,這樣無論是EF還是數據庫,性能都會有所提高。當然太復雜的還是應該使用存儲過程。

七、預生成視圖

這個操作還很麻煩,當然只是第一次訪問時會影響性能,對一些訪問量不大的,不用也罷,畢竟你發布上去之后,有可能第一次訪問的就是你自己。

八、NoTracking

image

這個按微軟說性能影響不大,多數情況下我們也不需要它跟蹤,所以,加上算了。

九、using

image

十、Exists

在博客中看到的,感覺很有用

http://www.cnblogs.com/lori/p/3457430.html

EF架構~在ef中支持IQueryable級別的Contains被翻譯成了Exists,性能可以接受!

回到目錄

Entityframeworks很聰明

不錯,非常不錯!ef里的contains比linq to sql里的contains有了明顯的提升,事實上,是在進行SQL語句翻譯上有所提升,在linq to sql里不支持iqueryable的contains集合,它只支持本地集合進行contains,而本地集合的contains會被.net翻譯成sql語句是where in (...),即集合有多個元素,在in里就會被列舉多少次,這個在性能上是非常低下的,不提倡的,而且它還有長度限制,最多本地集合在linq to sql里是2000多個元素。

ef在這點上表示不錯,它為了防止你使用低下的查詢,它杜絕你在linq語句中去ToList()對象,這是不錯的選擇,對於EF中的contains的用法,我們一般是分兩步,第一查詢出要列舉的結果集,但不要ToList(),第二是使用contains語句,當EF把它發到SQL端時,這個語句被翻譯成了exist,我們知道,這種查詢的性能一定是比where in強的,不說SQL本身就說網絡傳輸,它也一定比前者省了不少,呵呵。

Entityframeworks中正確使用Contains語句的Demo

錯誤的

   var linq = (from data1 in GetUser().Where(i => i.UserID <= 50) select data1.UserID).ToList();

   var linq2 = GetUser_StudyRecord().Where(i => linq.Contains(i.UserID.Value)).ToList();

SQL語句截圖

正確的

 var linq = (from data1 in GetUser().Where(i => i.UserID <= 50) select data1.UserID);//IQueryable<int>,一個查詢計划

 var linq2 = GetUser_StudyRecord().Where(i => linq.Contains(i.UserID.Value)).ToList();

SQL語句截圖

 

對我這種散修來說,未查找更多實用的,路過的老大看到有錯誤指點一下


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM