>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
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.