天天看點

提高entity framework 性能,要注意哪些事情.

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

  我發現現在有不少博友,都反對使用EF架構,說它性能低.其實隻要你用的好,性能不是問題,經過測試,它也會接近ado.net的通路了.

       當然如果對EF不了解,随便亂用,确實會引來性能問題.因為EF的查詢語句都是自己生成的.如果不注意,它會多次查詢資料庫,或用效率不高的語句去查詢.

      下面我就把我們在項目中遇到的問題,現我把他總結出來.以供大家參考.當然還有一些沒有列出來的,希望各網友也一起提供一下,以避免大家少走彎路.

分頁的時候,盡量在資料庫裡面去分頁.在我實際中的項目,我就發現我同僚由于他不了解EF屬性,它的分頁都是做在記憶體中分頁.下面請看他的代碼.

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

         像上面的語句,他會先把資料從資料庫中查出來,然後才分頁.

          正确的寫法應如下:

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

     2.盡量禁用延遲加載,盡量使用預加載和顯式加載查詢.

       Vs 預設生成的代碼,是啟用了延遲加載的.這樣往往是有些開發人員在不了解的情況下,進行了多次往資料庫查詢.如下的代碼.

        using (SchoolContainer db = new SchoolContainer())

        {

           var list = db.People.Where(ent => ent.PersonID < 30).ToList();

            foreach (var people in list)

            {

                foreach (var ent in people.StudentGrades)

                {

                    Console.WriteLine(ent.Grade);

                }

              }

        }

 如果啟用延遲加載,這樣會造成多次往返資料庫查詢的.勢必造成性能低下.

是以我們在這裡應該使用預加載.代碼如下:

var list = db.People.Include("StudentGrades").Where(ent => ent.PersonID < 30).ToList();

當然使用了預加載,延遲加載也不會查詢多次.但怕在程式員寫代碼時,忘了要預加載,如果啟用了延遲加載,那麼就會多次查詢資料庫.如果不啟用,那麼程式員就擷取不了資料,這樣他就馬上明白,要進行預加載了.

當然任何事情不是絕對的.如果被查詢的對象,過于複雜,就要慎用預加載

       3.注意事務的簡短性.

在使用事務時,我們要盡量把查詢語句或者其他響事務外的語句移在事務外執行.不然讓一個事務的時間太長了,就容易引起資源死鎖的問題.我上次就優化我一個同僚的代碼,他代碼裡就把所所有不相關的東西都放在事務裡執行,這樣就造成事務的時間太長,當用壓力測時,馬上就出現資源被鎖的錯誤.

       4.查詢出來的實體,如果不考慮删除和修改,請用NoTracking

       5.批量删除和修改,不要用先把實體查詢出來,然後再逐個删除和修改.這樣會産生大量的語句,效率肯定會低.

對于這個解決方式一是直接用sql語句執行,二是可以用自己寫個擴充方法來操作.雖然有不少人反對這方法.但我個人是傾向于自己寫個擴充方法.這樣,有2個好處.一是給開發人員使用簡單.二是友善管理. 雖然也有網友提出用ObjectStateManager.ChangeObjectState 來實作批量删除,但我是沒有找到相關的批量删除方法.而且這個也經常會出異常.

        6.使用已編譯的查詢,雖然到EF5.0, LINQ 查詢是自動緩存的.但使用編譯查詢會比自動緩存的效率高.

        7.預生成視圖,

          具體操作如下:

<a href="http://blogs.msdn.com/b/appfabriccat/archive/2010/08/06/isolating-performance-with-precompiled-pre-generated-views-in-the-entity-framework-4.aspx">http://blogs.msdn.com/b/appfabriccat/archive/2010/08/06/isolating-performance-with-precompiled-pre-generated-views-in-the-entity-framework-4.aspx</a>

        8.還有一點,就是對于複雜的查詢,我們要随時監控生成的查詢語句.

           畢竟EF生成的語句,往往比我們生成的語句更加複雜,這個時候我們就要考慮是否通過其他方式來提高性能.