我想创建一个通用方法,允许我使用Linq到Sitecore(.Net 4.5)搜索Sitecore 7索引。
这将用于各种搜索,例如:
我可以创建一个非常通用的搜索方法,适用于所有类型的页面。它为Where子句提供了适用于所有类型搜索的通用模板谓词。
但是,对于上面的搜索,我还需要为Where子句添加特定谓词,并为Order By等添加特定表达式。目的是为每种类型的搜索创建子类,这将实现这些细节。
我已经压缩了一些代码,如下所示。在此我尝试为新页面搜索添加特定功能。
所有页面类都来自“Base”。
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 the template id.
Expression<Func<T, bool>> templatePredicate = PredicateBuilder.False<T>();
templatePredicate = templatePredicate.Or(baseItem => (baseItem.TemplateIdFromIndex.Equals("8b1fc00c76314d32b8e1bce93dd41ccd")));
// Create a predicate for a news page search.
Expression<Func<NewsPageBase, bool>> datePredicate = PredicateBuilder.False<NewsPageBase>();
datePredicate = datePredicate.And(newsPage => newsPage.ArticleDate < DateTime.Now);
// 1. outerPredicate = outerPredicate.And(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);
}
此代码符合并运行。
但是,如果我取消注释标记为[1]的行,编译器会错误地使用特定的新闻页谓词来定义通用模板谓词。
错误是“方法的类型参数'Sitecore.ContentSearch.Linq.Utilities.PredicateBuilder.And(System.Linq.Expressions.Expression&gt;,System.Linq.Expressions.Expression&gt;)'无法从使用中推断出来”
如果我取消注释标记为[2]的行,则会出现类似的错误。
如何创建具有每种搜索类型特定功能的通用方法?
答案 0 :(得分:2)
按如下方式修改代码可以实现您的需求..
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);
}
我所做的改变是:
Expression<Func<T, bool>>
,但将其强制转换为object
首先解决此问题,编译器会抱怨。答案 1 :(得分:1)
我找到了解决方法。
而不是:
Expression<Func<NewsPageBase, bool>> datePredicate = PredicateBuilder.False<NewsPageBase>();
datePredicate = datePredicate.And(newsPage => newsPage.ArticleDate < DateTime.Now);
您可以使用:
Expression<Func<T, bool>> innerPredicate = PredicateBuilder.False<T>();
innerPredicate = innerPredicate.Or(item => ((DateTime)item[(ObjectIndexerKey)"article_date"] < DateTime.Now));
对于OrderBy子句,您可以使用:
searchQuery = searchQuery.OrderByDescending(item => item[(ObjectIndexerKey)"article_date"]);
如果您的基类是Sitecore类“SearchResultItem”的子类,那么这将有效。