Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Contains At Least All in Entity Framework

I have the following 2 entitys in my db.

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; }

}

I need to filter these articles based on the tag IDs that are passed into my action.

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...


}

For example, if I passed in 1, 2, 3 into the action, only articles which had these 3 tags or more would be returned.

How can I achieve this?

Thanks for the great response!

All your answers produced the correct result so I did some quick, basic profiling in sql and this was the results based on your queries.

Query Results

like image 682
heymega Avatar asked Jun 22 '15 15:06

heymega


2 Answers

Use Except() and Any() like

ApplicationDbContext
    .Articles
    .Where(a => tags.Except( a.Tags.Select( t => t.Id ).ToList() ).Any() == false)

Except() will give you the items from the first list which do not exist in the second list

The Except operator produces the set difference between two sequences. It will only return elements in the first sequence that don't appear in the second.

like image 82
AmmarCSE Avatar answered Sep 28 '22 16:09

AmmarCSE


This should do it:

ApplicationDbContext.Articles.Where(a => tags.All(t => a.Tags.Any(at => at.Id == t)));
like image 45
adam0101 Avatar answered Sep 28 '22 15:09

adam0101