根据实体框架中的常用标签选择相关文章

时间:2012-03-16 08:20:04

标签: c# entity-framework c#-4.0 linq-to-entities entity-framework-4.3

我有这些实体:

public class Article {
    public int Id { get; set; }
    public virtual IList<Tag> Tags { get; set; }
}

public class Tag {
    public int Id { get; set; }
    public virtual IList<Article> Articles { get; set; }
}

我按Article加载Tag,如下所示:

var articleByTags = context.Articles.Include(a => a.Tags).FirstOrDefault(a => a.Id == someId);

现在,我如何获得一篇文章列表,这些文章必须与所选文章共同使用?你能帮我吗?

2 个答案:

答案 0 :(得分:2)

好问题。这是解决方案:

// you should have a list of primitive types to use in SQL IN keyword
var ids = articleByTags.Tags.Select(t => t.Id).ToList();
var query = (from article in context.Articles
              // do you want same article again? NO! so remove the current article
             where article.Id != articleByTags.Id
             // this line would create a IN statement to SQL
             // if you don't want to load common tags, you can merge this line
             // by the next it, and just create a COUNT()
             let commonTags = article.Tags.Where(tag => ids.Contains(tag.Id))
             let commonCount = commonTags.Count()
             // there as any?
             where commonCount > 0
             // ascending! not descending! you want most common 
             orderby commonCount ascending
             // create your projection
             select new {
                 Id = article.Id,
                 Title = article.Title,
                 Tags = article.Tags,
                 Commons = commonTags,
                 CommonCount = commonCount
                 // or any property you want...
            })
            // how many you want to take? for example 5
            .Take(5)
            .ToList();

答案 1 :(得分:0)

我想你想要这样的东西:

var listOfMustHaveTags = new List<Tag>(); // Should be filled with Tags
var articleByCommonTags = context.Articles.Where(n => n.Tags.All(listOfMustHaveTags.Contains));

如果要求表明必须包含至少一个代码,请使用.All()更改.Any()