2017-06-30 39 views
0

起初我有這樣的名單:如何加入列表和大型列表/表使用LINQ

List<Car> cars = db.Car.Where(x => x.ProductionYear == 2005).ToList(); 

然後我試圖加入這個列表使用LINQ這樣的兩個大表:

var joinedList = (from car in cars 
        join driver in db.Driver.ToList() 
        on car.Id equals driver.CarId 
        join building in db.Building.ToList() 
        on driver.BuildingId equals building.Id 
        select new Building 
        { 
        Name = building.Name; 
        Id = building.Id; 
        City = building.City; 
        }).ToList(); 

兩個DriverBuilding表有大約100萬行。當我運行這個連接時,出現內存異常。我怎樣才能使這個連接工作?我應該對數據庫進行連接操作嗎?如果是的話,我怎樣才能將cars列表攜帶到數據庫?提前致謝。

+1

'db.Driver.ToList()''刪除ToList()'從這個,它會阻止在內存中獲取整個驅動表。同樣來自'db.Building'。 –

+0

@RahulSingh我這樣做,但我仍然得到例外。 – jason

+0

你有什麼打算用這些藏品呢? –

回答

2

即使您已刪除.ToList(更換.AsQueryable(

AsQueryable已快於ToList而AsEnumerable enter image description here

enter image description here

  • 如果您創建一個IQueryable,那麼查詢可能是co nverted爲sql ,如果你在運行查詢之前創建一個IEnumerable,然後所有的行會被拉入
    內存對象的數據庫服務器

  • 上運行。

  • 在這兩種情況下,如果你不調用ToList()或ToArray的(),然後查詢
    將每次使用的時間執行,所以,比如說,你有一個
    IQueryable的和您填寫4名單從它的框,然後查詢將 對數據庫運行的4倍。

所以以下中使用了LINQ查詢

var joinedList = (from car in db.Car.Where(x => x.ProductionYear == 2005).AsQueryable() 
       join driver in db.Driver.AsQueryable() 
       on car.Id equals driver.CarId 
       join building in db.Building.AsQueryable() 
       on driver.BuildingId equals building.Id 
       select new Building 
       { 
       Name = building.Name, 
       Id = building.Id, 
       City = building.City, 
       }).ToList(); 
+0

'db.Driver'和'db.Driver.AsQueryable'有什麼區別? – user3185569

3

即使你刪除你的加入,你的代碼仍然可以把所有數據裏面的.ToList()調用和執行內存的加入,而不是在SQL服務器。這是因爲您在加入時使用本地名單cars。下面的應該解決您的問題:

var joinedList = (from car in db.Car.Where(x => x.ProductionYear == 2005) 
        join driver in db.Driver 
        on car.Id equals driver.CarId 
        join building in db.Building 
        on driver.BuildingId equals building.Id 
        select new Building 
        { 
        Name = building.Name; 
        Id = building.Id; 
        City = building.City; 
        }).ToList(); 

您可以刪除最後.ToList(),並做一些paging如果你希望在結果中得到太多的記錄。

+0

現在它使用較少的內存,但仍佔用超過1 GB的內存。沒有辦法減少這種情況嗎?有沒有辦法在完成加入後釋放內存?感謝你的回答。 – jason

+0

@jason'joinedList'應該是你在上面的代碼執行後需要擔心的一切。所有不再使用的東西都標記爲垃圾回收(並且將在GC啓動時的某個時間點收集)。但是,如果'joinedList'項目太多,請檢查我答案中的最後一行並實施分頁。 – user3185569

+0

在一種情況下,我在該連接中出現了內存不足異常。我做了你所做的一切。 – jason

1

在使用LINQ(可以)時,首先不要嘗試ToList(),但要確保在極少數情況下儘量少使用ToList()。 每次你會得到OutOfMemoryException當表中包含許多行。 所以,這裏是你的問題的代碼:))

var joinedList = (from car in db.Car.GetQueryable().Where(x => x.ProductionYear == 2005) 
       join driver in db.Driver.GetQueryable() on car.Id equals driver.CarId 
       join building in db.Building.GetQueryable() on driver.BuildingId equals building.Id 
       select new Building 
       { 
       Name = building.Name; 
       Id = building.Id; 
       City = building.City; 
       }).ToList(); 
+1

*在非常罕見的情況*這是錯誤的。如果您遵循影響性能和往返的建議,則可以執行多個枚舉。好的建議是理解延遲執行,那麼你可以知道何時使用'.ToList()',而不是。 – user3185569

+0

是的,我完全同意你的觀點,如果你是優秀的編碼人員,那麼在理解執行之後,你會知道何時使用以及在何處使用。有時它基於業務邏輯提供幫助。 –