国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

7行代碼看EntityFramework是如何運行

2019-11-17 01:45:31
字體:
供稿:網(wǎng)友

7行代碼看EntityFramework是如何運行

2014-09-16 08:47 by IT農(nóng)民!, ... 閱讀, ... 評論, 收藏, 編輯

這段時間在項目中運用Entity Framework作為底層數(shù)據(jù)交互框架。一個字,爽。不僅提高了開發(fā)效率,省了很多代碼,而且數(shù)據(jù)庫也規(guī)范了很多。按照網(wǎng)上的一些教程初步學(xué)習(xí),然后實際運用了,再結(jié)合MVC ,開發(fā)一個模塊的增刪改查,那真是一個爽歪歪。但是,隨著項目不斷完善,數(shù)據(jù)表越來越多,關(guān)聯(lián)性也越來越復(fù)雜,問題也逐漸露出水面。首先最大的問題是數(shù)據(jù)查詢慢。有個影響點是Linq里的Count(),查閱了網(wǎng)上許多資料,都沒有好的解決方法。這個問題暫時不說,如果那位大師有良策,還不忘賜教。

影響查詢慢主要問題在于數(shù)據(jù)查詢,說白了不了解EF是如何執(zhí)行sql查詢的,什么時候進行sql查詢?以什么方式進行sql查詢的?

我做了一個demo,以微軟的Northwind作為數(shù)據(jù)庫,有個Customers表和Orders表,Orders表里有個字段CustomerID,是Customers表的外鍵。代碼如下:

1 NorthwindEntities db = new NorthwindEntities();2 var query = db.Customers.AsEnumerable();3 for (int idx = 0; idx < 2; idx++)4 {5      var customer = query.ElementAt(idx);6       var order = customer.Orders.FirstOrDefault();7        if (order != null)8               Console.WriteLine(order.OrderID);9  }

在跟蹤代碼時,同時將SQL Server PRofiler打開。代碼執(zhí)行到2行,sql跟蹤器并沒有執(zhí)行sql語句。當(dāng)執(zhí)行第5行時,sql跟蹤器有了反應(yīng)。

sql 是查詢了customers表。再往下執(zhí)行到第6行時,

根據(jù)外鍵customerid 去查詢orders訂單。如此。每循環(huán)一次。數(shù)據(jù)庫就會執(zhí)行2次查詢。如果有查詢結(jié)果有20條,就會有40次查詢,如果關(guān)聯(lián)的表越多。查詢的次數(shù)就會越多。

系統(tǒng)查詢能不慢嗎。

解決方法:

 1             NorthwindEntities db = new NorthwindEntities(); 2             ////取消EF的延遲加載 3             db.Configuration.LazyLoadingEnabled = false; 4             ////一次性查詢出customers和Orders數(shù)據(jù),并利用ToList()放入到內(nèi)存中 5             var query = db.Customers.Include("Orders").ToList(); 6             for (int idx = 0; idx < 2; idx++) 7             { 8                 var customer = query.ElementAt(idx); 9                 var order = customer.Orders.FirstOrDefault();10                 if (order != null)11                     Console.WriteLine(order.OrderID);12             }

取消EF的延遲加載。利用Include()將所需要對象一次性查詢出來。并利用ToList()將數(shù)據(jù)存入內(nèi)存中。

這是優(yōu)化后的sql運行跟蹤。我們會發(fā)現(xiàn),只實現(xiàn)了一次查詢,sql語句用了left join的方式將數(shù)據(jù)一次性查詢出來。每次循環(huán)也只會訪問內(nèi)存中。

總結(jié):

從這4行代碼中,我們發(fā)現(xiàn)

1.AsEnumerable()和 AsQueryable() 是延遲執(zhí)行,當(dāng)具體使用對象時才會執(zhí)行sql;ToList() 在使用時就已經(jīng)執(zhí)行,并數(shù)據(jù)存入內(nèi)存中。2.EF 本身默認(rèn)的是延遲加載,每個關(guān)聯(lián)的查詢,每次循環(huán)的查詢都是要執(zhí)行數(shù)據(jù)庫的。取消延遲加載,利用Include方法,可以一次性將所有數(shù)據(jù)查詢出來。以上觀點純屬個人經(jīng)驗總結(jié),歡迎各位大鳥發(fā)表看法,小菜向大家學(xué)習(xí)了。

【編后語】

博文發(fā)表后,筆者看到許多同行的討論,也學(xué)到不少東西。筆者這里申明,自己并非黑EF。正是看到了EF的強大,才開始使用它。但是,任何東西都要學(xué)懂。就好比筆者來說,之前的用法,導(dǎo)致一個10行的列表,數(shù)據(jù)庫查詢就執(zhí)行了好幾百次。雖然這是在開發(fā)中問題不是很明顯,但是一旦正式使用,這絕對是一個隱藏的炸彈。

EF很強大,但是,不懂它心的人,只會讓自己傷心!

與廣大程序員共勉!

【再編后語】

筆者很不平。多數(shù)同行并沒有看懂這篇博文的意思。循環(huán)2次是模擬展示列表。例如,我有表格要展示這個客戶的訂單,沒有分頁。按照前面那種方案

 customer.Orders.FirstOrDefault();這個客戶有多少可訂單,數(shù)據(jù)庫執(zhí)行多少次。而第二種方案:
var query = db.Customers.Include("Orders").ToList();數(shù)據(jù)庫只執(zhí)行一次就可以。展示表格的時候都是從內(nèi)存中獲取。這就是是個明顯數(shù)據(jù)庫性能的問題。筆者虛心向大家討教!

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 日喀则市| 杭锦后旗| 桂东县| 林周县| 昭觉县| 溆浦县| 蓬安县| 通化市| 长顺县| 达孜县| 灌阳县| 绥芬河市| 茂名市| 靖西县| 新余市| 贵溪市| 台北县| 吉林市| 五河县| 麻江县| 浮梁县| 昭通市| 汽车| 榆林市| 集贤县| 保靖县| 新化县| 长垣县| 普定县| 湟中县| 本溪| 治多县| 永宁县| 丹棱县| 乌拉特后旗| 名山县| 柞水县| 张掖市| 包头市| 曲阜市| 建水县|