我需要优化这个Linq查询

时间:2011-11-17 04:06:07

标签: c# asp.net linq

我有一个需要优化的Linq查询。

修改

我想我想要做的就是选择第一个表中的所有行,但选择Survey,CB和Science表中的最后一行或默认行......

修改

当这创建一个查询时,我针对整个查询点击了一次数据库,然后再次针对每个结果我从第一个查询返回。因此,如果TestClass返回30个结果,那么我会为调查对象多次点击DB 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();

3 个答案:

答案 0 :(得分:2)

您可以从您的Utopia表中进行选择,然后加入第二个表来获取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()将实际执行查询的那部分(或整个查询)。

答案 1 :(得分: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 ..

答案 2 :(得分:0)

您对我的真实查询的复杂性表明您应该将此LINQ语句移动到存储过程中,然后再调用它。

我建议这样做是因为(a)您可以完全控制查询的执行方式,(b)在TSQL中分析和性能优化查询要容易得多。这是我们过去在大型项目中使用的策略,当结果集生成变得非常重要时。

我还建议您使用AutoMapper执行将sproc结果传输到DTO的任务,因为您似乎有一个接近1:1的映射