【问题标题】:LINQ2SQL: Passing predicate to the .Count(Func<T>,bool) in a subqueryLINQ2SQL:将谓词传递给子查询中的 .Count(Func<T>,bool)
【发布时间】:2010-12-22 19:38:21
【问题描述】:

我对 linq2sql 中的谓词有疑问。我想要做的是将条件分成一个静态类,然后在我的查询中使用它们。我创建了一个带有一些函数的静态类:

public static class CountingFilters
    {
        public static  Func<CountingItem, bool> TotalItemsPredicate
            = ci =>
                      !ci.Deleted && ci.OdinProduct != null &&
                      ((ci.OdinProduct.NotOriginal == null && !ci.OdinProduct.Deleted)
                       || ((ci.OdinProduct.NotOriginal == ci.OdinProduct.GUID) && ci.OdinProduct.Deleted))
                      && (!ci.OdinProduct.Temp);

        public static  Func<CountingItem, bool> AlreadyCountedPredicate
            = ci =>
                TotalItemsPredicate(ci) && ci.CountedAmount.HasValue;
     }

如果我这样使用它:

var count = CountingFacade.GetCountingItems().Count(CountingFilters.TotalItemsPredicate);

一切正常,我得到了结果。 但是当我尝试创建绑定到gridview的投影时,像这样:

var result = from f in countinglist
   let alreadyCounted = f.CountingItems.Count(CountingFilters.AlreadyCountedPredicate)
   let total = f.CountingItems.Count(CountingFilters.TotalItemsPredicate)
   select new CountingProjection
   {
          AlreadyCountedProducts = alreadyCounted,
          Description = f.Description,
          NumberOfProducts = total,
          PlannedDate = f.PlannedDate.Value,
          Site = f.Site,
          Status = f.Status,
          Type = f.Type,
          GUID = f.GUID,

   };

它抛出异常“用于查询运算符'Count'的不支持的重载。”出于某种原因,据我所知,我的谓词没有被翻译成 SQL……谁能告诉我,我做错了什么?提前致谢。

【问题讨论】:

    标签: .net linq-to-sql


    【解决方案1】:

    您通常需要返回 Expression> 才能将它们翻译成 SQL。

    看看predicate builder

    还有this值得一看

    【讨论】:

    • 如果我用 Expression 覆盖我的谓词,像这样:public static Expression> TotalItemsPredicate,它会抛出完全相同的异常。
    【解决方案2】:

    另一种方法是使用扩展方法。如果您不喜欢深入研究 Expression 等,它将为您节省大量时间。您的代码将如下所示:

    public static class CountingFilters
    {
         public static int TotalItems(this IEnumerable<CountingItem> source)
         {
             return source.Count(ci => !ci.Deleted && ci.OdinProduct != null &&
                              ((ci.OdinProduct.NotOriginal == null && !ci.OdinProduct.Deleted)
                               || ((ci.OdinProduct.NotOriginal == ci.OdinProduct.GUID) && ci.OdinProduct.Deleted))
                              && (!ci.OdinProduct.Temp));
         }
    
         public static int AlreadyCounted(this IEnumerable<CountingItem> source)
         {
             return source.Count(ci => !ci.Deleted && ci.OdinProduct != null &&
                              ((ci.OdinProduct.NotOriginal == null && !ci.OdinProduct.Deleted)
                               || ((ci.OdinProduct.NotOriginal == ci.OdinProduct.GUID) && ci.OdinProduct.Deleted))
                              && (!ci.OdinProduct.Temp) && ci.CountedAmount.HasValue);
         }
    }
    
        var result = from f in countinglist
           let alreadyCounted = f.CountingItems.AlreadyCounted()
           let total = f.CountingItems.TotalItems()
           select new CountingProjection
           {
                  AlreadyCountedProducts = alreadyCounted,
                  Description = f.Description,
                  NumberOfProducts = total,
                  PlannedDate = f.PlannedDate.Value,
                  Site = f.Site,
                  Status = f.Status,
                  Type = f.Type,
                  GUID = f.GUID,
    
           };
    

    【讨论】:

    • +1。这就是我处理过滤器扩展方法的方式。在某些情况下,甚至可以选择通用 T 版本(在适当的情况下)
    • 是的,这会起作用,但我已经为我的问题争论了将近 8 个小时,现在我真的很想找出答案
    • @mrblack:您收到异常的原因是 LINQ 提供程序无法反向编译您的函数以将其转换为 SQL。这就是您需要返回表达式树(如果 LINQ 提供程序支持)或使用扩展方法的原因。我更喜欢扩展方法方法,尽管使用IQueryable 而不是IEnumerable
    猜你喜欢
    • 1970-01-01
    • 2013-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-18
    • 1970-01-01
    • 2021-06-17
    • 2020-08-05
    相关资源
    最近更新 更多