目标:
我有一个小部件,试图将具有匹配标签的博客帖子返回到当前项目。
问题:
所以我已经在我的小部件中获取了当前的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
答案 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);
}