>Andy , 2023/05/11 # IEnumerable與IQueryable ## 概述 兩者都是用來執行LINQ的Interface,主要的差別在於查詢的方式與執行的時機。 先定義一個DbContext,以便後續說明,並假設Book資料表中有10筆資料。 ```csharp var dbContext = new DbContext(); ``` ## IEnumerable 從資料庫中撈取資料,存至記憶體中,並在記憶體中篩選。 ```csharp //此時的data,已經將資料載入記憶體當中,記憶體有全部10筆資料。 IEnumerable<Book> Edata = dbContext.Book; //即使在定義變數時加入了where條件式,記憶體中同樣是載入全部10筆資料 IEnumerable<Book> filterEdata = dbContext.Book.Where(x => x.Id ==1); ```  ## IQueryable 在IDE中寫好的IQueryable只是"查詢狀態",此時還沒執行資料庫的查詢,因此不會有資料載入記憶體的行為。若指派某些會得到"明確結果"的function,如Count()、ToList()等,此時才會執行SQL查詢指令,取得查詢結果。 以下程式定義的變數都會得到IQueryable物件,實際上不會去執行SQL查詢,而是將查詢轉換成Expresion,並將所有查詢條件存於Provider中。 ```csharp //此時的data是"查詢狀態",資料還未載入記憶體中。 IQueryable<Book> Qdata = dbContext.Book; //在定義變數時加入條件式,也不會將"查詢狀態"載入記憶體中。 IQueryable<Book> filterQdata = dbContext.Book.Where(x => x.Id == 1); ``` 以下程式會真的執行SQL查詢,IQueryable介面會將Expression傳遞給Provider,由Provider轉譯成T-SQL後,從DB中取得資料,得到"明確結果" ``` //下面兩行程式才會執行SQL指令,並將查詢的資料載入記憶體中。 var book = filterData.ToList(); var book = filterData.Count(); ```  如果在宣告變數時不指定資料型態,會預設指定IQueryable物件。 ```csharp //data的資料型態是IQueryable物件 var data = dbContext.Book; ``` ## 注意事項 了解原理之後,才能避免浪費效能的寫法。 由於IEnymerable與IQueryable都有延遲載入的機制,因此使用之前應該先將查詢結果保存,以避免重新查詢。 以下程式是不良示範,每跑一次迴圈都會訪問一次資料庫,如果查詢結果資料量大,就會造成效能降低的負面影響。 ```csharp IEnumerable<Book> query = dbContext.Book; foreach(var item in query) { var book name = query.Where(x => x.Price < 300); //do } ``` 存成List就可以避免這個問題。 ```csharp List<Book> query = dbContext.Book.ToList(); foreach(var item in query) { var book name = query.Where(x => x.Price < 300); //do } ``` ###### tags: `back-end`
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up