带有特定where/order by子句的通用Linq

带有特定where/order by子句的通用Linq,linq,generics,sitecore,sitecore7,Linq,Generics,Sitecore,Sitecore7,我想创建一个通用方法,允许我使用Linq to Sitecore(.Net 4.5)搜索Sitecore 7索引 这将用于各种搜索,例如: 获取前5个最新新闻页面 获取最后20个事件页面 通用网站搜索 等等等等等等 我可以创建一个非常通用的搜索方法,它适用于所有类型的页面。它为Where子句提供了一个通用模板谓词,该谓词适用于所有类型的搜索 但是,对于上面的搜索,我还需要为Where子句添加特定的谓词,并为Order By等添加特定的表达式。目的是为每种类型的搜索创建子类,从而实现这些细节

我想创建一个通用方法,允许我使用Linq to Sitecore(.Net 4.5)搜索Sitecore 7索引

这将用于各种搜索,例如:

  • 获取前5个最新新闻页面
  • 获取最后20个事件页面
  • 通用网站搜索
  • 等等等等等等
我可以创建一个非常通用的搜索方法,它适用于所有类型的页面。它为Where子句提供了一个通用模板谓词,该谓词适用于所有类型的搜索

但是,对于上面的搜索,我还需要为Where子句添加特定的谓词,并为Order By等添加特定的表达式。目的是为每种类型的搜索创建子类,从而实现这些细节

我已经压缩了一些代码,如下所示。在本文中,我尝试为新页面搜索添加特定功能

所有页面类都派生自“Base”

公共虚拟只读集合搜索(),其中T:Base,new() { 列表结果=新列表(); 使用(IProviderSearchContext=ContentSearchManager.GetIndex(“sitecore\u web\u index”).CreateSearchContext()) { 表达式outerPredicate=PredicateBuilder.True(); //为模板id创建谓词。 表达式templatePredicate=PredicateBuilder.False(); templatePredicate=templatePredicate.Or(baseItem=>(baseItem.TemplateIdFromIndex.Equals(“8b1fc00c76314d32b8e1bce93dd41ccd”)); //为新闻页面搜索创建谓词。 表达式datePredicate=PredicateBuilder.False(); datePredicate=datePredicate.And(newsPage=>newsPage.ArticleDatenewsPage.ArticleDate).Take(5); IQueryable searchQuery=context.GetQueryable().Where(outerPredicate); 结果=searchQuery.ToList(); } 返回新的只读集合(结果); } 此代码符合并运行

但是,如果我取消注释标记为[1]的行,编译器将错误提示我将通用模板谓词与特定的新闻页谓词进行Anding

错误是“无法根据用法推断方法“Sitecore.ContentSearch.Linq.Utilities.PredicateBuilder.And(System.Linq.Expressions.Expression>,System.Linq.Expressions.Expression>)”的类型参数”

如果我取消注释标记为[2]的行,则会出现类似的错误


如何创建一个通用方法,该方法具有针对每种搜索类型的特定功能?

我找到了一个解决方法

而不是:

Expression<Func<NewsPageBase, bool>> datePredicate = PredicateBuilder.False<NewsPageBase>();
datePredicate = datePredicate.And(newsPage => newsPage.ArticleDate < DateTime.Now);

如果您的基类是从Sitecore类“SearchResultItem”中派生出来的子类,那么这将起作用。

按如下方式修改代码可以满足您的需要

public virtual ReadOnlyCollection<T> Search<T>() where T : Base, new()
    {
        List<T> results = new List<T>();

        using (IProviderSearchContext context = ContentSearchManager.GetIndex("sitecore_web_index").CreateSearchContext())
        {
            Expression<Func<T, bool>> outerPredicate = PredicateBuilder.True<T>();

            // Create a predicate for a news page search.
            Expression<Func<NewsPageBase, bool>> datePredicate = PredicateBuilder.True<NewsPageBase>();
            datePredicate = datePredicate.And(newsPage => newsPage.ArticleDate < DateTime.Now);

            //outerPredicate = outerPredicate.And((Expression<Func<T,bool>>)(object)datePredicate);
            outerPredicate = outerPredicate.And((Expression<Func<T, bool>>)(object)datePredicate);

            // 2. IQueryable<T> searchQuery = context.GetQueryable<T>().Where(outerPredicate).OrderByDescending(newsPage => newsPage.ArticleDate).Take(5);
            IQueryable<T> searchQuery = context.GetQueryable<T>().Where(outerPredicate);

            results = searchQuery.ToList();
        }

        return new ReadOnlyCollection<T>(results);
    }
公共虚拟只读集合搜索(),其中T:Base,new() { 列表结果=新列表(); 使用(IProviderSearchContext=ContentSearchManager.GetIndex(“sitecore\u web\u index”).CreateSearchContext()) { 表达式outerPredicate=PredicateBuilder.True(); //为新闻页面搜索创建谓词。 表达式datePredicate=PredicateBuilder.True(); datePredicate=datePredicate.And(newsPage=>newsPage.ArticleDatenewsPage.ArticleDate).Take(5); IQueryable searchQuery=context.GetQueryable().Where(outerPredicate); 结果=searchQuery.ToList(); } 返回新的只读集合(结果); } 我所做的改变是:

  • 删除了未使用的templatePredicate——我不确定您是否打算使用它,或者在压缩原始代码时忘记删除它
  • 使用PredicateBuilder.True而不是PredicateBuilder.False创建datePredicate-这是在.And()中使用所必需的,否则不会返回任何结果
  • 在outerPredicate.And()中使用的I(un)box日期谓词。如果您试图将datePredicate强制转换为
    表达式
    ,但将其强制转换为
    对象
    首先会解决此问题,编译器会对此进行投诉
  • Expression<Func<T, bool>> innerPredicate = PredicateBuilder.False<T>();
    innerPredicate = innerPredicate.Or(item => ((DateTime)item[(ObjectIndexerKey)"article_date"] < DateTime.Now));
    
    searchQuery = searchQuery.OrderByDescending(item => item[(ObjectIndexerKey)"article_date"]);
    
    public virtual ReadOnlyCollection<T> Search<T>() where T : Base, new()
        {
            List<T> results = new List<T>();
    
            using (IProviderSearchContext context = ContentSearchManager.GetIndex("sitecore_web_index").CreateSearchContext())
            {
                Expression<Func<T, bool>> outerPredicate = PredicateBuilder.True<T>();
    
                // Create a predicate for a news page search.
                Expression<Func<NewsPageBase, bool>> datePredicate = PredicateBuilder.True<NewsPageBase>();
                datePredicate = datePredicate.And(newsPage => newsPage.ArticleDate < DateTime.Now);
    
                //outerPredicate = outerPredicate.And((Expression<Func<T,bool>>)(object)datePredicate);
                outerPredicate = outerPredicate.And((Expression<Func<T, bool>>)(object)datePredicate);
    
                // 2. IQueryable<T> searchQuery = context.GetQueryable<T>().Where(outerPredicate).OrderByDescending(newsPage => newsPage.ArticleDate).Take(5);
                IQueryable<T> searchQuery = context.GetQueryable<T>().Where(outerPredicate);
    
                results = searchQuery.ToList();
            }
    
            return new ReadOnlyCollection<T>(results);
        }