2013-02-20 30 views
1

我有一段代碼表現糟糕,需要重新引導它以在啓動.ToList之前引入適當的where子句,但是,這就是我卡住的地方。性能不佳的查詢需要重寫

目前的代碼看起來這艾克(約,我已經採取了一些搜索標準出來,使其更容易顯示)

var Widgets = from b in _caspEntities.Widgets.Include("WidgetRegionLogs") 
        .Include("WidgetStatusLogs").Include("WidgetVoltageTests") 
         select b; 

IEnumerable<Widget> results = Widgets.ToList(); 
if (comboBoxRegion.SelectedValue.ToString() != "0") 
{ 
    results = from b in results 
       where b.CurrentRegionLog != null && b.CurrentRegionLog.RegionId == int.Parse(comboBoxRegion.SelectedValue.ToString()) 
       select b; 
} 

if (comboBoxStatus.SelectedValue != null) 
{ 
    results = from b in results 
       where b.CurrentStatusLog != null && b.CurrentStatusLog.StatusId == comboBoxStatus.SelectedValue.ToString() 
       select b; 
} 

if (txtCode.Text.Trim().Length > 0) 
{ 
    results = from b in results 
       where b.CodeNumber == txtCode.Text.Trim() 
       select b; 
} 

dataGridViewWidget.DataSource = results.ToList(); 

我可以寫SQL容易不夠,基本上是模型簡單,我有一個Widget它有一個RegionLog和一個StatusLog,兩者都存儲歷史記錄。通過按WidgetID進行分組並選擇最新的更新日期(然後轉到區域和狀態表以獲取實際值),從中檢索當前區域和狀態。

所以,我需要將其轉換成LINQ,但說實話,我沒有線索,但肯和願意學習。在我的腦海中,我想我需要在where子句中添加更好的一些,然後在應用where子句之後再執行Widget.toList。我正在努力與CurrentRegionLogCurrentStatusLog的概念,因爲它們沒有填充,直到我運行IEnumerable

如果任何人都可以給一些指點,我會很感激,感謝

編輯 - 添加

public BatteryRegionLog CurrentRegionLog 
    { 
     get { return _currentRegionLog; } 
    } 

    private BatteryRegionLog _currentRegionLog 
    { 
     get 
     { 
      if (this.BatteryRegionLogs.Count > 0) 
      { 
       BatteryRegionLog log = this.BatteryRegionLogs.OrderByDescending(item => item.LastModifiedDate).First(); 
       return log; 
      } 
      else 
      { 
       return null; 
      } 
     } 
    } 

回答

0

您可以撰寫本查詢:

if (comboBoxRegion.SelectedValue.ToString() != "0") 
    { 
     var id = int.Parse(comboBoxRegion.SelectedValue.ToString() 
     Widgets = from b in Widgets 
        let currentRegionLog = 
         b.BatteryRegionLogs 
         .OrderByDescending(item => item.LastModifiedDate) 
         .FirstOrDefault() 
        where currentRegionLog.RegionId == id) 
        select b; 
    } 
    ... // Same for the other criteria. 

    dataGridViewWidget.DataSource = Widgets.ToList(); 

整個查詢是不是你之前執行做ToList()。由於所有內容都轉換爲SQL,因此不需要空值檢查b.CurrentRegionLog != null。如果沒有CurrentRegionLog,SQL將評估b.CurrentRegionLog.RegionId == id

編輯

由於CurrentRegionLog是你Widget類的計算性能就不能轉換成SQL。我努力將計算屬性的代碼以只使用基本導航屬性的方式整合到查詢中,因此EF可以再次將其轉換爲SQL。

+0

感謝格特,我已經試過這是通過得到以下錯誤..指定的類型成員'CurrentRegionLog'不支持LINQ to Entities。只支持初始化,實體成員和實體導航屬性。我想我需要設置這個地方,但我抓住了一些吸管:-( – MikeH 2013-02-20 10:29:50

+0

「CurrentRegionLog」背後的代碼是什麼?它應該是一個導航屬性。 – 2013-02-20 10:31:55

+0

私人BatteryRegionLog _currentRegionLog { 得到 { 如果(this.BatteryRegionLogs.Count> 0){ BatteryRegionLog日誌= this.BatteryRegionLogs.OrderByDescending(項目=> item.LastModifiedDate)。首先(); 返回日誌; } else { return null; }} } 在 – MikeH 2013-02-20 10:34:19

0

嘗試刪除此行:

IEnumerable<Widget> results = Widgets.ToList(); 

,只是使用Widgets變量你在頂部

.ToList()進入數據庫並將所有數據重定義爲實體。

,如果你不叫.ToList()查詢仍在「開放」爲where條款

+0

謝謝Jens,我肯定聽起來有點愚蠢,但是不會失去將數據導入數據網格的功能嗎? – MikeH 2013-02-20 10:36:46

+0

@MikeH有沒有達姆問題:)我不相信它會。在你的代碼示例中,你實際上調用了'.ToList()',這會將完整的查詢(包括where cluase)引發到數據庫。 – 2013-02-20 10:58:58

+0

謝謝Jens,我真的需要上C#課程!我試過這個,並得到以下錯誤「指定的類型成員'CurrentRegionLog'在LINQ to Entities中不受支持。只有初始化,實體成員和實體導航屬性都支持」 – MikeH 2013-02-20 11:07:47