EF迴圈迭代導致如此嚴重的效能丟失,你知道?

2021-09-22 17:09:22 字數 2807 閱讀 6518

在工作當中呢,沒怎麼用到過ef,所以為了遺忘這一部分知識,偶爾會去寫寫小的demo,偶然機會在ef迴圈迭代中發現居然影響效能這麼嚴重,當我們在用時或許大概也許可能都曾這樣寫過,但是你注意到了嗎,你懷疑過嗎?這就是本節所要討論的話題。若有錯誤,請批評指出。

關於基礎知識我們就不廢話了哈,我們假設這樣乙個場景(不一定嚴謹,只是為了引出話題):當在下單中,如果有多個人下單,此時我們需要通過訂單id去得到客戶id。在這一場景中我們給出乙個訂單類以及訂單處理類。如下:

//

訂單類public

class

order

public

int orderid

public

int customerid

public

string filed1

public

string filed2

public

string filed3

public

string filed4

public

string filed5

}

//

訂單處理類

public

class

orderprocess

public

int customerid

}

訂單類是poco類存於資料庫中,而訂單處理類為將訂單類進行dto的類,我們將訂單id傳到訂單處理類中,通過訂單類來獲取到客戶id並賦給訂單處理類中的客戶id。

為了大家可能方便測試,將其餘說了很多次的對映類以及上下文都給出來。

//

訂單對映類

public

class ordermap : entitytypeconfiguration

}

//

ef上下文以及預熱

public

class

efdbcontext : dbcontext

//////

通過反射一次性將表進行對映

/// ///

protected

override

void

onmodelcreating(dbmodelbuilder modelbuilder)}}

在資料庫中對訂單表生成了20萬條資料。我們在訂單處理類中隨機插入100條訂單id,如下:

var orderprocesslist = new list();

for (int i = 0; i < 100; i++)

;orderprocesslist.add(orderprocess);

}

為了將訂單類中客戶id賦給訂單處理類中客戶id,你是不是會像如下這樣操作呢?

var context = new

efdbcontext();

foreach (var op in

orderprocesslist)

此時我們來測試下耗費的時間。

//替換成

var order = context.set().asnotracking().firstordefault(o => o.orderid == op.orderid);

此時看看演示結果:

此時耗費的時間為1.7秒,當然有時會更短,反正比上述加了變更追蹤情況的耗費時間要少。

到了這裡你是不是就覺得已經很滿足了呢?是不是覺得已經得到了很大的改善了呢?要是這樣關閉變更追蹤就可以解決了問題,那我這篇文章你說還有什麼意義呢?好了廢話不多說。本文討論的話題就在於ef迴圈迭代問題,難道僅僅只有上述一種方式能達到我們的需求嗎,上述我們將ef迭代放在了遍歷訂單處理類中,我們難道就不能事先得到符合條件的訂單id,然後直接取到對應的客戶id呢?思路來了,說完就開始幹。

(1)篩選出符合訂單處理類中的訂單。

var ordertoprocessids = orderprocesslist.select(o =>o.orderid).tolist();

var allorders = context.set().asnotracking().where(o => ordertoprocessids.contains(o.orderid));

(2)將符合條件的訂單轉換成以訂單id為鍵的字典。

var allordersdictionary = allorders.todictionary(o => o.orderid);

foreach (var op in

orderprocesslist)

這樣不就解決了每次都要去迭代訂單嗎。接下來我們來測試比較改良一和改良二中耗費的時間。

本節我們驗證了在ef迴圈迭代中會導致效能的丟失,我們不經意間的操作就導致效能的丟失,有時候轉換思維很重要,不僅僅只侷限於固定思維,從上面可以看出:能夠避免的應該盡量避免在遍歷資料時去進行ef的迴圈迭代。好了,本來打算早點睡覺的,偶然發現這樣也會導致效能的丟失,於是馬不停蹄導致本文的產生。

Deiphi編譯優化導致的死迴圈

請看下面這段 procedure tform1.button1click sender tobject varstrcolor string i,r,g,b,p integer strlist tstringlist begin strcolor medt.text strlist tstringl...

解決建構函式導致的迴圈依賴

假設有下面三個類 public classa.public classb.public classc.那麼問題來了,該如何建立乙個a的物件呢?a a newa newb newc newa wtf 我們發現,無法為a建立物件,這個例子揭示了一種由建構函式導致的迴圈依賴問題。a b c三個類之間通過構...

迴圈(迭代)與遞迴的區別

迴圈 迭代 與遞迴的區別 1。遞迴演算法與迭代演算法的設計思路區別在於 函式或演算法是否具備收斂性,當且僅當乙個演算法存在預期的收斂效果時,採用遞迴演算法才是可行的,否則,就不能使用遞迴演算法。當然,從理論上說,所有的遞迴函式都可以轉換為迭代函式,反之亦然,然而代價通常都是比較高的。但從演算法結構來...