2011-11-17 102 views
1

我有一個需要優化的Linq查詢。我需要優化此Linq查詢

編輯

我想對所有我所試圖做的是選擇在第一個表中的所有行,但選取的調查,CB和科學表的最後或默認的行...

編輯

當這將創建一個查詢,我打一次數據庫整個查詢,然後再一次爲每一個結果我得到第一個查詢回來。因此,如果TestClass返回30個結果,那麼我會再次爲調查對象點擊數據庫30次。

我真的需要一個更好的方式來完成這項工作。

在此先感謝!

實例查詢

return (from xx in db.test      
     select new TestClass     { 
     Added_By_User_ID = xx.Added_By_User_ID, 
     Survey = (from ru in db.Utopia 
        where ru.Province_ID == xx.Province_ID 
        orderby ru.uid descending 
        select ru).Take(1).ToList(), 
       }).ToList(); 

房地產查詢

return (from xx in db.Utopia_Province_Data_Captured_Gens 
       where xx.Owner_Kingdom_ID == ownerKingdomID 
       where kingdomList.Contains((Guid)xx.Kingdom_ID) 
       select new ProvinceClass 
       { 
        Kingdom_ID = xx.Kingdom_ID, 
        Kingdom_Island = xx.Kingdom_Island, 
        Kingdom_Location = xx.Kingdom_Location, 
        Owner_Kingdom_ID = xx.Owner_Kingdom_ID, 
        Province_ID = xx.Province_ID, 
        Province_Name = xx.Province_Name, 
        Owner_User_ID = xx.Owner_User_ID, 
        Race_ID = xx.Race_ID, 
        Updated_By_DateTime = xx.Updated_By_DateTime, 
        Networth = xx.Networth, 
        Land = xx.Land, 
        Monarch_Display = xx.Monarch_Display, 
        Owner = xx.Owner, 
        Sub_Monarch = xx.Sub_Monarch, 
        CB_Updated_By_Province_ID = xx.CB_Updated_By_Province_ID, 
        uid = xx.uid, 
        Formatted_By = xx.Formatted_By, 
        Utopian_Day_Month = xx.Utopian_Day_Month, 
        Utopian_Year = xx.Utopian_Year, 
        Ruler_Name = xx.Ruler_Name, 
        Personality_ID = xx.Personality_ID, 
        Nobility_ID = xx.Nobility_ID, 
        Money = xx.Money, 
        Daily_Income = xx.Daily_Income, 
        Food = xx.Food, 
        Runes = xx.Runes, 
        Population = xx.Population, 
        Peasents = xx.Peasents, 
        Peasents_Non_Percentage = xx.Peasents_Non_Percentage, 
        Trade_Balance = xx.Trade_Balance, 
        Building_Effectiveness = xx.Building_Effectiveness, 
        Military_Efficiency_Off = xx.Military_Efficiency_Off, 
        Military_Efficiency_Def = xx.Military_Efficiency_Def, 
        Draft = xx.Draft, 
        Soldiers = xx.Soldiers, 
        Soldiers_Regs_Off = xx.Soldiers_Regs_Off, 
        Soldiers_Regs_Def = xx.Soldiers_Regs_Def, 
        Soldiers_Elites = xx.Soldiers_Elites, 
        War_Horses = xx.War_Horses, 
        //Prisoners = xx.Prisoners, 
        Military_Net_Off = xx.Military_Net_Off, 
        Military_Net_Def = xx.Military_Net_Def, 
        Military_Current_Off = xx.Military_Current_Off, 
        Military_Current_Def = xx.Military_Current_Def, 
        Mil_Training = xx.Mil_Training, 
        Mil_Wage = xx.Mil_Wage, 
        Mil_Overall_Efficiency = xx.Mil_Overall_Efficiency, 
        Mil_Total_Generals = xx.Mil_Total_Generals, 
        Wizards = xx.Wizards, 
        Wizards_Value_Type = xx.Wizards_Value_Type, 
        Thieves = xx.Thieves, 
        Thieves_Value_Type = xx.Thieves_Value_Type, 
        Plague = xx.Plague, 
        Monarch_Vote_Province_ID = xx.Monarch_Vote_Province_ID, 
        Protected = xx.Protected, 
        Hit = xx.Hit, 
        Honor = xx.Honor, 
        Province_Notes = xx.Province_Notes, 
        CB_Export_Line = xx.CB_Export_Line, 
        Army_Out = xx.Army_Out, 
        Army_Out_Expires = xx.Army_Out_Expires, 
        Updated_By_Province_ID = xx.Updated_By_Province_ID, 
        SOM_Updated_By_Province_ID = xx.SOM_Updated_By_Province_ID, 
        SOM_Updated_By_DateTime = xx.SOM_Updated_By_DateTime, 
        CB_Updated_By_DateTime = xx.CB_Updated_By_DateTime, 
        CB_Requested = xx.CB_Requested, 
        CB_Requested_Province_ID = xx.CB_Requested_Province_ID, 
        SOM_Requested = xx.SOM_Requested, 
        SOM_Requested_Province_ID = xx.SOM_Requested_Province_ID, 
        SOS_Requested = xx.SOS_Requested, 
        SOS_Requested_Province_ID = xx.SOS_Requested_Province_ID, 
        Survey_Requested = xx.Survey_Requested, 
        Survey_Requested_Province_ID = xx.Survey_Requested_Province_ID, 
        Last_Login_For_Province = xx.Last_Login_For_Province, 
        Date_Time_User_ID_Linked = xx.Date_Time_User_ID_Linked, 
        Added_By_User_ID = xx.Added_By_User_ID, 
        NoteCount = (from yy in db.Utopia_Province_Notes 
           where yy.Province_ID == xx.Province_ID 
           select yy).Count(), 
        SOM = (from uu in db.Utopia_Province_Data_Captured_Type_Militaries 
          where uu.Province_ID == xx.Province_ID 
          where uu.Owner_Kingdom_ID == ownerKingdomID 
          where uu.DateTime_Added == (from ru in db.Utopia_Province_Data_Captured_Type_Militaries //datetime can be same for multiple items. 
                 where ru.Province_ID == xx.Province_ID 
                 where ru.Owner_Kingdom_ID == ownerKingdomID 
                 orderby ru.uid descending // To get the last most inserted rows 
                 select ru.DateTime_Added).FirstOrDefault() 
          select uu).ToList(), 


        SOS = (from zz in db.Utopia_Province_Data_Captured_Sciences 
          where ru.Province_ID == xx.Province_ID 
          where ru.Owner_Kingdom_ID == ownerKingdomID 
          orderby ru.uid descending 
          select ru).Take(1).ToList(), 
        Survey = (from ru in db.Utopia_Province_Data_Captured_Surveys 
           where ru.Province_ID == xx.Province_ID 
           where ru.Owner_Kingdom_ID == ownerKingdomID 
           orderby ru.uid descending 
           select ru).Take(1).ToList(), 
        CB = (from ru in db.Utopia_Province_Data_Captured_CBs 
          where ru.Province_ID == xx.Province_ID 
          where ru.Owner_Kingdom_ID == ownerKingdomID 
          orderby ru.uid descending 
          select ru).Take(1).ToList() 
       }).ToList(); 
+0

LINQ2SQL就是我使用 –

+0

你幹得嵌套查詢,所以你所看到的行爲是可以預料的。如果您編寫了類似的SQL,則會遇到同樣的問題。 Polity建議,簡單的嵌套查詢可以用連接替代。 –

+0

您可以通過讓此表按id鏈接到這些表來消除「排序,取一個」查詢。那麼你有一個歷史,但你只有一個「當前」價值。支持一個列表也是有點奇怪的,但是讓這個列表每個只有一個值。我不知道Linq to SQL,但是在Linq to Entities中,可以使用'.Include(「SomeProperty」)'強制同時檢索數據。這隻適用於你有一個省份實體和適當的DB FK關係。 –

回答

2

您可以從您的烏托邦表中選擇並加入第二個用於獲取USER_ID,如:

from ru in db.Utopia 
join xx in test on ru.Province_ID equals xx.Province_ID 
orderby ru.uid descending 
select new TestClass 
{ 
    Added_By_User_ID = xx.Added_By_User_ID, 
    Survey = ru 
} 

更新的真正查詢

這是一個巨大的查詢,你應該考慮一種基於連接的方法,正如我建議的那樣,並且基於Jim McKeeth提出的本地緩存。或者你應該一起創建一個新的表格。

當你需要從可選的數據多表查詢,您可以執行左連接:

from ru in db.Utopia 
join user in db.Users on ru.UserId equals user.Id // User is required 
join survey in db.Surveys on ru.Province_ID equals survey.Province_ID into j1 
from survey in j1.DefaultIfEmpty() // Survey is optional (left join) 
join address in db.Address on ru.UserId equals address.UserId into j2 
from survey in j2.DefaultIfEmpty() // Address is optional (left join) 
orderby ru.uid descending 
select new TestClass 
{ 
    Added_By_User_ID = xx.Added_By_User_ID, 
    Survey = survey, 
    Street = address.Street, 
    UserName = new UserName 
    { 
     FirstName = user.FirstName, 
     LastName = user.LastName 
    } 
} 

注意的量加入會影響您的查詢的性能。遲早會用高速緩存找到更好的方法會變得更高效。

另一個需要注意的是,在查詢中調用ToList()將實際執行該部分查詢(或整個查詢)。

+0

這只是一個例子...也許我應該發佈真正的查詢.. –

+0

@Scott - 嘗試先建立它自己,這是一個很好的鍛鍊:) – Polity

+0

我發佈了真正的查詢。 –

0

喜歡的東西:

from xx in db.test 
join ru in db.Utopia on xx.Province_ID equals ru.Province_ID 
orderby ru.uid descending 
select new .. 
+0

如何獲得最後一個完整的RU表格?正如你所看到的,我想要一個全新的對象的整個調查... –

0

你真正的查詢的複雜性給我指示,你應該提出這個LINQ語句轉換成一個存儲過程,然後調用該代替。我建議這樣做,因爲(a)您將完全控制查詢的執行方式,並且(b)在TSQL中分析和性能優化您的查詢更容易。這是我們過去在大型項目中使用的策略,當時結果集的生成變得不平凡。

我也要建議你使用AutoMapper執行存儲過程的結果轉移到你的DTO的任務,因爲你似乎有接近1:1映射

+0

視圖也將是一個合適的包裝。你可以加入視圖。不確定您是否可以將sproc結果加入臨時表中。 –

+0

好點。我想我仍然會使用sproc,因爲它可以返回多個結果集,並且可以輕鬆地將上面提到的內容列表中的內容提取出來。 我只能想象生成運行此查詢的可笑的低效TSQL! – geoffreys