如何筛选Orchard CMS Query中的相关内容部件

时间:2013-07-09 22:04:49

标签: c# linq orchardcms

目标:

我有一个小部件,试图将具有匹配标签的博客帖子返回到当前项目。

问题:

所以我已经在我的小部件中获取了当前的ContentItem,并且我已经返回了该ContentItem的TagsPart

var itemTagsPart = _contentManager.Get<TagsPart>(currentContentItem.Id);

我现在正在尝试创建一个查询,以返回具有匹配TagName的标记记录的博客帖子。

var blogs = _contentManager.Query(VersionOptions.Published, "BlogPost")
                .Join<TagsPartRecord>().Where(tpr => tpr.Tags.Any(tag => itemTagsPart.CurrentTags.Any(t => t.TagName == tag.TagRecord.TagName)))
                .Slice(part.MaxPosts);

不幸的是,在过滤返回的TagsPartRecord记录的谓词上,我得到一个空引用异常。我无法准确地减少哪个字段会导致这种情况,但是我在谓词中添加了空检查(上面的代码将它们全部删除以保持它在这里干净)。实施例

var blogs = _contentManager.Query(VersionOptions.Published, "BlogPost")
                .Join<TagsPartRecord>().Where(tpr => tpr.Tags != null && tpr.Tags.Any(tag => tag != null && itemTagsPart.CurrentTags.Any(t => t.TagName != null &&  t.TagName == tag.TagRecord.TagName)))
                .Slice(part.MaxPosts);

我甚至尝试过严格itemTagsPart.CurrentTags.ToList()

以下是我得到的错误。但是,我读到了posted Question 你不能做这种类型的过滤器,至少不是我的方式。如何根据匹配的tagsParts过滤返回的博客帖子?

版本: 1.7

错误:

Orchard.ContentManagement.Drivers.Coordinators.ContentPartDriverCoordinator - NullReferenceException thrown from IContentPartDriver by TrueFit.RelatedBlogPosts.Drivers.RelatedBlogPostsWidgetDriver
System.NullReferenceException: Object reference not set to an instance of an object.
at NHibernate.Linq.Visitors.WhereArgumentsVisitor.GetExistsCriteria(MethodCallExpression expr)
at NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitMethodCall(MethodCallExpression expr)
at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
at NHibernate.Linq.Visitors.WhereArgumentsVisitor.GetExistsCriteria(MethodCallExpression expr)
at NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitMethodCall(MethodCallExpression expr)
at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
at NHibernate.Linq.Visitors.ExpressionVisitor.VisitLambda(LambdaExpression lambda)
at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
at NHibernate.Linq.Visitors.WhereArgumentsVisitor.VisitUnary(UnaryExpression expr)
at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
at NHibernate.Linq.Visitors.RootVisitor.HandleWhereCall(MethodCallExpression call)
at NHibernate.Linq.Visitors.RootVisitor.VisitMethodCall(MethodCallExpression expr)
at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
at NHibernate.Linq.Visitors.NHibernateQueryTranslator.Translate(Expression expression, QueryOptions queryOptions)
at Orchard.ContentManagement.DefaultContentQuery.Where[TRecord](Expression`1 predicate) in c:\inetpub\Orchard\src\Orchard\ContentManagement\DefaultContentQuery.cs:line 89
 at Orchard.ContentManagement.DefaultContentQuery.ContentQuery`2.Orchard.ContentManagement.IContentQuery<T,TR>.Where(Expression`1 predicate) in c:\inetpub\Orchard\src\Orchard\ContentManagement\DefaultContentQuery.cs:line 237
 at TrueFit.RelatedBlogPosts.Drivers.RelatedBlogPostsWidgetDriver.Display(RelatedBlogPostsWidgetPart part, String displayType, Object shapeHelper)
at System.Dynamic.UpdateDelegates.UpdateAndExecute4[T0,T1,T2,T3,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3)
at Orchard.ContentManagement.Drivers.ContentPartDriver`1.Orchard.ContentManagement.Drivers.IContentPartDriver.BuildDisplay(BuildDisplayContext context) in c:\inetpub\Orchard\src\Orchard\ContentManagement\Drivers\ContentPartDriver.cs:line 27
at Orchard.ContentManagement.Drivers.Coordinators.ContentPartDriverCoordinator.<>c__DisplayClassa.<BuildDisplay>b__9(IContentPartDriver driver) in c:\inetpub\Orchard\src\Orchard\ContentManagement\Drivers\Coordinators\ContentPartDriverCoordinator.cs:line 47
at Orchard.InvokeExtensions.Invoke[TEvents](IEnumerable`1 events, Action`1 dispatch, ILogger logger) in c:\inetpub\Orchard\src\Orchard\InvokeExtensions.cs:line 17

1 个答案:

答案 0 :(得分:0)

我正在开发一个基于单个标记名称过滤博客帖子的网站:

// Get the blog that contains the posts you want to filter
BlogPart blog = _contentManager.Query<BlogPart, BlogPartRecord>(VersionOptions.Published)
                                                      .Join<TitlePartRecord>()
                                                      .Where(t => t.Title == "your-blog-name")
                                                      .Slice(0, 1).FirstOrDefault();

// Query for blog posts that contain a tag called "my-tag"
IEnumerable<BlogPostPart> posts = _contentManager.Query(VersionOptions.Published, "BlogPost")
                                               .Join<CommonPartRecord>()
                                               .Where(cr => cr.Container == blog.Record.ContentItemRecord)
                                               .Join<TagsPartRecord>()
                                               .Where(tpr => tpr.Tags.Any(t => t.TagRecord.TagName == "my-tag"))
                                               .WithQueryHints(new QueryHints().ExpandRecords<TagsPartRecord>().ExpandParts<TagsPart>())
                                               .Slice(maxPosts)
                                               .Select(ci => ci.As<BlogPostPart>());

基于此,我猜(虽然我没有测试过)使用标签名称的字符串集合,您可以更改此行:

.Where(tpr => tpr.Tags.Any(t => t.TagRecord.TagName == "my-tag"))

到此行(您的标记名称集合为myTags):

.Where(tpr => tpr.Tags.Any(t => myTags.Contains(t.TagRecord.TagName)))

如果这不起作用,您可以创建博客文章部分列表,循环遍历您的标记名称集合,并使用原始查询获取每个标记名称的博客帖子:

// Get the blog that contains the posts you want to filter
BlogPart blog = _contentManager.Query<BlogPart, BlogPartRecord>(VersionOptions.Published)
                                                          .Join<TitlePartRecord>()
                                                          .Where(t => t.Title == "your-blog-name")
                                                          .Slice(0, 1).FirstOrDefault();
List<BlogPostPart> blogPosts = new List<BlogPostPart>();
foreach (string tag in myTags){
    // Query for blog posts that contain a tag called "my-tag"
    IEnumerable<BlogPostPart> posts = _contentManager.Query(VersionOptions.Published, "BlogPost")
                                                   .Join<CommonPartRecord>()
                                                   .Where(cr => cr.Container == blog.Record.ContentItemRecord)
                                                   .Join<TagsPartRecord>()
                                                   .Where(tpr => tpr.Tags.Any(t => t.TagRecord.TagName == tag))
                                                   .WithQueryHints(new QueryHints().ExpandRecords<TagsPartRecord>().ExpandParts<TagsPart>())
                                                   .Slice(maxPosts)
                                                   .Select(ci => ci.As<BlogPostPart>());
    blogPosts.AddRange(posts);
}