我的数据库中有以下2个实体。
public class Article
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
// Some code removed for brevity
public virtual ICollection<Tag> Tags { get; set; }
}
public class Tag
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
// Some code removed for brevity
public virtual ICollection<Article> Articles { get; set; }
}
我需要根据传递给我的操作的代码ID过滤这些文章。
public ActionResult FindAll(List<int> tags)
{
//
// I need to return all articles which have ALL the tags passed into this method
//
var query = ApplicationDbContext.Articles...
}
例如,如果我将1,2,3传递给动作,则只返回具有这3个或更多标签的文章。
我怎样才能做到这一点?
感谢您的好评!
您的所有答案都产生了正确的结果,因此我在sql中进行了一些快速,基本的分析,这是基于您的查询的结果。
答案 0 :(得分:3)
ApplicationDbContext
.Articles
.Where(a => tags.Except( a.Tags.Select( t => t.Id ).ToList() ).Any() == false)
Except()
将为您提供第一个列表中第二个列表中不的项目
Except运算符产生两个序列之间的集合差异。 它只会返回第一个序列中不会出现的元素 在第二。
答案 1 :(得分:2)
这应该这样做:
ApplicationDbContext.Articles.Where(a => tags.All(t => a.Tags.Any(at => at.Id == t)));
答案 2 :(得分:2)
试试这个:
var query =from a in ApplicationDbContext.Articles
where a.Tags.Count(t => tags.Contains(t.Id)) == tags.Count
select a;
答案 3 :(得分:1)
通过IQueryable迭代地构建结果。
public ActionResult FindAll(List<int> tags)
{
var queryable = ApplicationDbContext.Articles.AsQueryable();
foreach(var t in tags)
{
queryable = queryable.Where(w => w.Tags.Any(a => a.Id == t));
}
queryable.AsEnumerable(); // stuff this into a viewmodel and return actionresult?
}
答案 4 :(得分:1)
这个怎么样?
var articles = ApplicationDbContext.Articles.Where (a => a.Tags.Select (t => t.Id).Intersect(tags).Count()>=tags.Count);
答案 5 :(得分:0)
使用此:
ApplicationDbContext.Articles.Where(a => tags.All(t => a.Tags.Contains(t)));