2012-04-23 15 views
2

MySQl 5.5.19、エンティティフレームワーク4.3を使用し、Sun提供のMySQLコネクタとDevArtの両方を変更してみました。リテラルがある場合、異なるクエリが生成されます

したがって、私は異なるクエリを生成する2つのステートメントを持っています。

var desserts = context.desserts 
    .AsQueryable() 
    .OrderBy(m => m.Id) 
    .Where(m => m.FlavorId == 123) 
    .ToList(); 

と第二は、最初のクエリは、このようなものになりますSQLクエリ生成

var desserts = context.desserts 
    .AsQueryable() 
    .OrderBy(m => m.Id) 
    .Where(m => m.FlavorId == someFlavorId) 
    .ToList(); 

です:最初はある

SELECT 
    Extent1.Id, 
    Extent1.Name, 
    Extent1.FlavorId 
FROM icecream.dessert AS Extent1 
WHERE Extent1.FlavorId = 123 
ORDER BY Extent1.Id ASC 

秒1を生成し、はるかに高価にクエリは次のようになります。

SELECT 
    Project1.Id, 
    Project1.Name, 
    Project1.FlavorId 
    FROM(
    SELECT 
     Extent1.Id, 
     Extent1.Name, 
     Extent1.FlavorId 
    FROM icecream.dessert AS Extent1 
    WHERE Extent1.FlavorId = 123 
) AS Project1 
    ORDER BY Project1.Id ASC 

そして、後者のクエリは、私のプロダクションコードで使用されているものです。私はなぜこれらの2つが異なるクエリになるのか混乱しています。

これを修正する方法はありますか?

答えて

2

これらは、最初のクエリが定数で渡され、2番目のクエリがパラメータで渡されるため、異なるSQLを生成します。

あなたは、このような場合は、述語のための発現作成する必要があります最初のクエリを模倣したい場合:

ParameterExpression parameter = Expression.Parameter(typeof(Dessert), "d"); 
Expression propertyOrField = Expression.PropertyOrField(parameter , "FlavorId"); 
Expression constant = Expression.Constant(someFlavorId, typeof(long?)); 
Expression equal = Expression.Equal(propertyOrField, constant); 

var lambda = Expression.Lambda<Func<Dessert, bool>>(equal, parameter); 

var desserts = context.desserts 
    .AsQueryable() 
    .OrderBy(m => m.Id) 
    .Where(lambda) 
    .ToList(); 
+0

応答をありがとう。 2番目のSQLでEXPLAINを実行しましたが、それは良くありません。プライマリは968K行の "ALL"タイプで、Extraは "filesortを使用しています"であり、派生物はキーを使用し、534K行です。リテラルを持つものによって生成されたクエリは534Kの行を持つ "ref"型であり、 "どこで使用するか" - リテラルでないクエリでは明らかに遅くなります。 – itsmatt

+0

また、あなたの式は別のカラムではうまくいきますが、この特定のもの( "FlavorId")はnullが許されます。任意のアイデアをどのようにnullableで動作するようにするには? – itsmatt

+0

@itsmatt - 興味深いことに、MySqlの方が最適化に優れていると思っていて、両方のクエリが同じ実行計画になると思います。 – Aducci

関連する問題