2011-07-21 4 views
0

ここにコードを入力してください 'let'キーワードを使用するいくつかのLinqクエリがあります。彼らは3.5でうまく動作しますが、私は4.0で非常に奇妙な動作を見ています。3.5と比較して4.0で異なる動作をするLinqクエリ

例:

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つのネストされたループを列挙することを可能にします。オプション内に1つ、オプション内で各地域調整用に1つ。

foreach (var bookOption in query) 

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

4.0の問題は、生成されたSQLは、(プロファイラでトレース)は、任意のWHERE句なしRegionPriceAdjustmentテーブルからの選択であることです。これは、コマンドがタイムアウトすることを意味します(問合せの他の部分の兆候がないため、とにかく間違っています)。

"let"を.Includeに置き換えようとしましたが、これは遅延読み込みを有効にしても動作しますが、各PriceTypeの動的SQL文が生成されます(8個あります)。私は遅延読み込みを無効にしようとしましたが、これは間違いなくPriceTypeが読み込まれないためエラーです。私は2つのセレクトを区切りで使用しようとしましたが、同じ問題が発生します。

4.0では、POCOとEntityFramework DLLにDbContextオブジェクトを使用しています。私はObjectContextを試してみませんでしたが、DbContextはObjectContextをラップするので、違いはありません。

これはなぜですか?助言がありますか?

おかげで、イヴ・

編集:ここでは

は3.5とSQLです:ここでは

[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 

は私だけ(POCOのを使用して)4.1で得るものです:

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のトレースもありません......

答えて

0

私は回避策を見つけました。

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から照会しています3行目に、したがって、内部結合をしている:私の新しいクエリは次のようです。もちろん、コメントアウトされている行は必要ありません。もちろん、

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

クレイグによると、私のクエリは、より簡素化することができるが、それはわかりやすさの理由であったように私はそれのほとんどを維持したい:私はクレイグStuntzによって優れた記事を読んで、この解決策を見つけました。

これは、元のクエリが4.1で機能しない理由を説明していません(ここでもwhereステートメントは完全に無視されます)が、すぐに受け入れることができます。

希望により、他の人に役立つは、YC

関連する問題