Linq-запрос с другим поведением в 4.0 по сравнению с 3.5 (пусть проблема с ключевыми словами?) - PullRequest
0 голосов
/ 21 июля 2011

Введите код здесь. У меня есть несколько запросов Linq, использующих ключевое слово let.Они отлично работают в 3.5, но я вижу очень странное поведение в 4.0.

Пример:

 var query1 =
            (from xVehicleOption in this.entities.VehicleOptionSet
                let regionPriceAdjustment = (from xOptionRegionPriceAdjustmentLeftOuter in this.entities.OptionRegionPriceAdjustmentSet
                                            where xOptionRegionPriceAdjustmentLeftOuter.VehicleTypeRegionId == this.vehicleTypeRegionId
                                            && xOptionRegionPriceAdjustmentLeftOuter.VehicleId == this.vehicleId
                                            && xOptionRegionPriceAdjustmentLeftOuter.VehicleOptionId == xVehicleOption.VehicleOptionId
                                            select new
                                            {
                                                xOptionRegionPriceAdjustmentLeftOuter,
                                                xOptionRegionPriceAdjustmentLeftOuter.xPriceType
                                            })
                where xVehicleOption.VehicleId == this.vehicleId
                && (xVehicleOption.OptionTypeId == 5 || xVehicleOption.OptionTypeId == 7)
                select new
                {
                    Name = xVehicleOption.DisplayName,
                    VehicleOptionId = xVehicleOption.VehicleOptionId,
                    SortOrder = xVehicleOption.SortOrder,
                    OptionAvailability = xVehicleOption.OptionAvailabilityDisplayName,
                    IsDefaultConfiguration = xVehicleOption.IsDefaultConfiguration,
                    OptionType = xVehicleOption.OptionTypeDisplayName,
                    RegionPriceAdjustment = regionPriceAdjustment
                }).OrderBy(o => o.SortOrder);

Это позволяет перечислять через 2 вложенных цикла.Один для каждой опции и один для каждой настройки региона внутри опции.

foreach (var bookOption in query)

{
    .......    
    foreach (var regionAdjustment in bookOption.RegionPriceAdjustment)    
    {    
         .......    
    }    
}

Проблема в 4.0 заключается в том, что сгенерированный SQL является таблицей SELECT FROM RegionPriceAdjustment БЕЗ любого предложения WHERE (отслеживается с помощью Profiler).Это означает, что время ожидания команды истекло (и в любом случае это неправильно, потому что нет признаков другой части запроса).

Я попытался заменить «let» на .Include, и это работает с отложенной загрузкойвключен, но генерирует динамический SQL-оператор для каждого PriceType (их 8, поэтому он не очень эффективен).Я попытался отключить отложенную загрузку, но это определенно дает мне ошибку, так как PriceType не загружается.Я пытался использовать два выбора, разделенных на в, но я получаю ту же проблему.

Кстати в 4.0, я использую POCOs и EntityFramework DLL с объектом DbContext.Я не пробовал с ObjectContext, но это не должно иметь никакого значения, так как DbContext обволакивает ObjectContext.

Любой ключ к пониманию того, почему он это делает?Есть предложения?

Спасибо, Ив

Отредактировано:

Вот SQL с 3.5:

[Project2].[VehicleOptionId] AS [VehicleOptionId],  
[Project2].[DisplayName] AS [DisplayName],  
[Project2].[OptionAvailabilityDisplayName] AS [OptionAvailabilityDisplayName],  
[Project2].[IsDefaultConfiguration] AS [IsDefaultConfiguration],  
[Project2].[SortOrder] AS [SortOrder],  
[Project2].[VehicleOptionId1] AS [VehicleOptionId1],  
[Project2].[CategoryId] AS [CategoryId],  
[Project2].[CategoryId1] AS [CategoryId1],  
[Project2].[DisplayName1] AS [DisplayName1],  
[Project2].[C1] AS [C1],  
[Project2].[C2] AS [C2],  
[Project2].[VehicleOptionId2] AS [VehicleOptionId2],  
[Project2].[VehicleTypeRegionId] AS [VehicleTypeRegionId],  
[Project2].[VehicleId] AS [VehicleId],  
[Project2].[PriceTypeId] AS [PriceTypeId],  
[Project2].[PriceAdjustment] AS [PriceAdjustment],  
[Project2].[ValueTypeId] AS [ValueTypeId],  
[Project2].[PriceTypeId1] AS [PriceTypeId1],  
[Project2].[DisplayName2] AS [DisplayName2] 
FROM ( SELECT  
        [Extent1].[VehicleOptionId] AS [VehicleOptionId],  
        [Extent1].[DisplayName] AS [DisplayName],  
        [Extent1].[OptionAvailabilityDisplayName] AS [OptionAvailabilityDisplayName],  
        [Extent1].[IsDefaultConfiguration] AS [IsDefaultConfiguration],  
        [Extent1].[SortOrder] AS [SortOrder],  
        [Extent2].[VehicleOptionId] AS [VehicleOptionId1],  
        [Extent2].[CategoryId] AS [CategoryId],  
        [Extent3].[CategoryId] AS [CategoryId1],  
        [Extent3].[DisplayName] AS [DisplayName1],  
        1 AS [C1],  
        [Project1].[VehicleOptionId] AS [VehicleOptionId2],  
        [Project1].[VehicleTypeRegionId] AS [VehicleTypeRegionId],  
        [Project1].[VehicleId] AS [VehicleId],  
        [Project1].[PriceTypeId] AS [PriceTypeId],  
        [Project1].[PriceAdjustment] AS [PriceAdjustment],  
        [Project1].[ValueTypeId] AS [ValueTypeId],  
        [Project1].[PriceTypeId1] AS [PriceTypeId1],  
        [Project1].[DisplayName] AS [DisplayName2],  
        [Project1].[C1] AS [C2] 
        FROM    [dbo].[KBB_V3_VehicleOption] AS [Extent1] 
        INNER JOIN [dbo].[KBB_V3_VehicleOptionCategory] AS [Extent2] ON ([Extent1].[VehicleOptionId] = [Extent2].[VehicleOptionId]) OR (([Extent1].[VehicleOptionId] IS NULL) AND ([Extent2].[VehicleOptionId] IS NULL)) 
        INNER JOIN [dbo].[KBB_V3_Category] AS [Extent3] ON ([Extent2].[CategoryId] = [Extent3].[CategoryId]) OR (([Extent2].[CategoryId] IS NULL) AND ([Extent3].[CategoryId] IS NULL)) 
        LEFT OUTER JOIN  (SELECT  
                [Extent4].[VehicleOptionId] AS [VehicleOptionId],  
                [Extent4].[VehicleTypeRegionId] AS [VehicleTypeRegionId],  
                [Extent4].[VehicleId] AS [VehicleId],  
                [Extent4].[PriceTypeId] AS [PriceTypeId],  
                [Extent4].[PriceAdjustment] AS [PriceAdjustment],  
                [Extent4].[ValueTypeId] AS [ValueTypeId],  
                [Extent5].[PriceTypeId] AS [PriceTypeId1],  
                [Extent5].[DisplayName] AS [DisplayName],  
                1 AS [C1] 
                FROM  [dbo].[KBB_V3_OptionRegionPriceAdjustment] AS [Extent4] 
                LEFT OUTER JOIN [dbo].[KBB_V3_PriceType] AS [Extent5] ON [Extent4].[PriceTypeId] = [Extent5].[PriceTypeId] ) AS [Project1] ON ([Project1].[VehicleTypeRegionId] = @p__linq__6) AND ([Project1].[VehicleId] = @p__linq__7) AND ([Project1].[VehicleOptionId] = [Extent1].[VehicleOptionId]) 
        WHERE (4 = [Extent1].[OptionTypeId]) AND ([Extent1].[VehicleId] = @p__linq__9) AND (22 = [Extent3].[CategoryTypeId]) 
)  AS [Project2] 
ORDER BY [Project2].[SortOrder] ASC, [Project2].[VehicleOptionId] ASC, [Project2].[VehicleOptionId1] ASC, [Project2].[CategoryId] ASC, [Project2].[CategoryId1] ASC, [Project2].[C2] ASC',N'@p__linq__6 int,@p__linq__7 int,@p__linq__9 int',@p__linq__6=0,@p__linq__7=261637,@p__linq__9=261637

Вот что я получаю только с 4.1(используя POCO):

    SELECT  
[Extent1].[VehicleOptionId] AS [VehicleOptionId],  
[Extent1].[VehicleTypeRegionId] AS [VehicleTypeRegionId],  
[Extent1].[VehicleId] AS [VehicleId],  
[Extent1].[PriceTypeId] AS [PriceTypeId],  
[Extent1].[PriceAdjustment] AS [PriceAdjustment],  
[Extent1].[ValueTypeId] AS [ValueTypeId] 
FROM [dbo].[KBB_V3_OptionRegionPriceAdjustment] AS [Extent1]

Как видите, нет предложения WHERE и нет следов остальной части SQL ......

1 Ответ

0 голосов
/ 27 июля 2011

Я нашел обходной путь, хотя. Мой новый запрос выглядит следующим образом:

var query = 
  (from xVehicleOption in this.entities.VehicleOptionSet 
   let regionPriceAdjustment = (from xOptionRegionPriceAdjustmentLeftOuter in xVehicleOption.XOptionRegionPriceAdjustment 
      where xOptionRegionPriceAdjustmentLeftOuter.VehicleTypeRegionId == this.vehicleTypeRegionId 
      //&& xOptionRegionPriceAdjustmentLeftOuter.VehicleId == this.vehicleId 
      //&& xOptionRegionPriceAdjustmentLeftOuter.VehicleOptionId == xVehicleOption.VehicleOptionId 
      select new 
      { 
       xOptionRegionPriceAdjustmentLeftOuter, 
       xOptionRegionPriceAdjustmentLeftOuter.XPriceType 
      }) 
   join xVehicleOptionCategory in this.entities.VehicleOptionCategorySet on xVehicleOption.VehicleOptionId equals xVehicleOptionCategory.VehicleOptionId 
   join xCategory in this.entities.CategorySet on xVehicleOptionCategory.CategoryId equals xCategory.CategoryId 
   where xVehicleOption.VehicleId == this.vehicleId 
   && xVehicleOption.OptionTypeId == 4 
   && xCategory.CategoryTypeId == 22 
   select new 
   { 
   Name = xVehicleOption.DisplayName, 
   VehicleOptionId = xVehicleOption.VehicleOptionId, 
   SortOrder = xVehicleOption.SortOrder, 
   OptionAvailability = xVehicleOption.OptionAvailabilityDisplayName, 
   IsDefaultConfiguration = xVehicleOption.IsDefaultConfiguration, 
   OptionType = xCategory.DisplayName, 
   RegionPriceAdjustment = regionPriceAdjustment 
   }).OrderBy(o => o.SortOrder); 

Обратите внимание, что в третьей строке я запрашиваю xVehicleOption вместо this.entities., Поэтому выполняю внутреннее соединение. Конечно, мне не нужны закомментированные строки. Я нашел это решение, прочитав отличную статью Крейга Стунца:

http://blogs.teamb.com/craigstuntz/2010/01/13/38525/

Конечно, по словам Крейга, мой запрос может быть еще более упрощенным, но я хотел оставить большую часть его, как это было сделано для удобства понимания.

Это все еще не объясняет, почему исходный запрос не работает в 4.1 (опять же, операторы where полностью игнорируются), но это приемлемый быстрый обходной путь.

Надеюсь, это поможет другим, YC

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...