【问题标题】:Different query generated if there is a literal如果存在文字,则生成不同的查询
【发布时间】:2012-05-04 06:57:49
【问题描述】:

使用 MySQl 5.5.19,实体框架 4.3,并尝试了 Sun 提供的 MySQL 连接器和 DevArt 连接器,两者之间没有任何区别。

所以,我有两个产生不同查询的语句。第一个是:

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

第二个是

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

第一个查询产生如下所示的 SQL 查询:

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

第二个生成的查询开销更大,如下所示:

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

当然,后一个查询是我的生产代码中使用的查询。我很困惑为什么这两个会导致不同的查询。

任何想法如何解决这个问题?

【问题讨论】:

    标签: mysql entity-framework linq-to-entities


    【解决方案1】:

    它们产生不同的 sql,因为您传递的第一个查询是常量,而第二个查询是您传递的参数。

    如果您想模仿第一个查询,您需要为 Where 谓词创建一个表达式,如下所示:

    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();
    

    【讨论】:

    • 感谢您的回复。我在第二个生成的 SQL 上运行了 EXPLAIN,它并不好 - 主类型是“ALL”类型,有 968K 行,Extra 是“使用文件排序”,派生使用一个键,有 534K 行。由文字产生的查询是“ref”类型,有 534K 行,“使用 where” - 使用非文字查询肯定会更慢。
    • 另外,您的表达式适用于不同的列,但这个特定的列(“FlavorId”)是一个可为空的 long。任何想法如何使它与可空值一起使用?
    • @itsmatt - 有趣的是,我原以为 MySql 在优化方面会更好,并且两个查询都会产生相同的执行计划。
    • @itsmatt - 尝试使用 FlavorId 时是否收到错误消息,或者结果不是应有的结果?
    • 它抛出 InvalidOperationException "二元运算符 Equal 没有为类型 'System.Nullable`1[System.Int64]' 和 'system.Int64' 定义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多