【问题标题】:best practice on conditional queries with linq to entities使用 linq to entity 进行条件查询的最佳实践
【发布时间】:2013-08-12 22:34:25
【问题描述】:

我经常发现自己在写这样的查询:

var voyages = db.VoyageRequests.Include("Carrier")
              .Where(u => (fromDate.HasValue ? u.date >= fromDate.Value : true) &&
                    (toDate.HasValue ? u.date <= toDate.Value : true) &&
                    u.Carrier != null &&
                    u.status == (int)VoyageStatus.State.InProgress)
              .OrderBy(u => u.date);

            return voyages;

在 where 语句中带有条件:

fromDate.HasValue ? u.date >= fromDate.Value : true

我知道另一种方法是:

 var voyages = db.VoyageRequests.Include("Carrier").Where(u => u.Carrier != null &&
                            u.status == (int)VoyageStatus.State.InProgress);

            if (fromDate.HasValue)
            {
                voyages = voyages.Where(u => u.date >= fromDate.Value);
            }

            if (toDate.HasValue)
            {
                voyages = voyages.Where(u => u.date <= toDate.Value);
            }

            return voyages.OrderBy(u => u.date);

当这两种方法转换为 SQL 表达式时,是否有任何可能影响性能的真正差异?

【问题讨论】:

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


    【解决方案1】:

    第二个查询将创建更简单的 SQL,因为 fromDate.HasValuetoDate.HasValue 的评估发生在客户端上。在第一个查询中,三元运算符作为 SQL 查询的一部分在数据库服务器上进行评估。 fromDatetoDate 都将作为常量传输到服务器,而在第二个查询中,只有当 .HasValuetrue 时。

    我们谈论的是 SQL 语句的长度增加了几个字节,我不认为三元组的服务器端评估对查询性能有任何显着影响。

    我会选择您认为更具可读性的内容。我个人会决定第二个查询。

    【讨论】:

      【解决方案2】:

      如果您想要简单的 SQL 和更具可读性的 C#,您可以按照 Viktor Mitev http://mentormate.com/blog/improving-linq-to-entities-queries/ 的建议创建一个扩展

      public static class WhereExtensions
      {
         // Where extension for filters of any nullable type
         public static IQueryable<TSource> Where<Tsource, TFilter>
                    (
                       this IQueryable <TSource> source, 
                       Nullable <TFilter> filter, 
                       Expression<Func<TSource, bool>> predicate
                    ) where TFilter : struct
         {
             if (filter.HasValue)
             {
                 source = source.Where(predicate);
             }
      
             return source;
         }
      
          // Where extension for string filters
         public static IQueryable<TSource> Where<TSource>
                   (
                      this IQueryable<TSource> source,   
                      string filter, 
                      Expression<Func<TSource, bool>> predicate
                   )
         {
             if (!string.IsNullOrWhiteSpace(filter))
             {
                 source = source.Where(predicate);
             }
      
             return source;
         }
      
          // Where extension for collection filters
         public static IQueryable<TSource> Where<TSource, TFilter>
                   (
                      this IQueryable<TSource> source, 
                      IEnumerable<TFilter> filter, 
                      Expression<Func<TSource, bool>> predicate
                   )
       {
           if (filter != null && filter.Any())
           {
               source = source.Where(predicate);
           }
      
           return source;
       }
      

      那么您的“第二个查询”将如下所示:

      var voyages = db.VoyageRequests.Include("Carrier")
      .Where(u => u.Carrier != null && u.status == (int)VoyageStatus.State.InProgress)
          .Where(u => u.date >= fromDate)
          .Where(u => u.date <= toDate)
          .OrderBy(u => u.date);
      

      我不知道它是否更具可读性,或者它是否会让一些开发人员感到困惑,因为直接从代码中读取过滤的哪个部分正在使用更困难。

      如果您将扩展函数命名为 WhereIfFilterNotNull 之类的名称(或有意义的名称 :-) 可能会更易读

      var voyages = db.VoyageRequests.Include("Carrier")
      .Where(u => u.Carrier != null && u.status == (int)VoyageStatus.State.InProgress)
          .WhereIfFilterNotNull(u => u.date >= fromDate)
          .WhereIfFilterNotNull(u => u.date <= toDate)
          .OrderBy(u => u.date);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-16
        • 1970-01-01
        • 1970-01-01
        • 2012-08-05
        相关资源
        最近更新 更多