在工作當中呢,沒怎麼用到過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
}
//訂單類是poco類存於資料庫中,而訂單處理類為將訂單類進行dto的類,我們將訂單id傳到訂單處理類中,通過訂單類來獲取到客戶id並賦給訂單處理類中的客戶id。訂單處理類
public
class
orderprocess
public
int customerid
}
為了大家可能方便測試,將其餘說了很多次的對映類以及上下文都給出來。
//訂單對映類
public
class ordermap : entitytypeconfiguration
}
//在資料庫中對訂單表生成了20萬條資料。我們在訂單處理類中隨機插入100條訂單id,如下:ef上下文以及預熱
public
class
efdbcontext : dbcontext
//////
通過反射一次性將表進行對映
/// ///
protected
override
void
onmodelcreating(dbmodelbuilder modelbuilder)}}
var orderprocesslist = new list();為了將訂單類中客戶id賦給訂單處理類中客戶id,你是不是會像如下這樣操作呢?for (int i = 0; i < 100; i++)
;orderprocesslist.add(orderprocess);
}
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();(2)將符合條件的訂單轉換成以訂單id為鍵的字典。var allorders = context.set().asnotracking().where(o => ordertoprocessids.contains(o.orderid));
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。遞迴演算法與迭代演算法的設計思路區別在於 函式或演算法是否具備收斂性,當且僅當乙個演算法存在預期的收斂效果時,採用遞迴演算法才是可行的,否則,就不能使用遞迴演算法。當然,從理論上說,所有的遞迴函式都可以轉換為迭代函式,反之亦然,然而代價通常都是比較高的。但從演算法結構來...