Using the ALL operator in linq to filter child items of EntitySet

前端 未结 2 1995
你的背包
你的背包 2020-12-21 19:25

I have a two objects as follows:

public class Item
{
    public int ItemId {get;set;}
    public string ItemName {get;set;}
    public List ItemTa         


        
2条回答
  •  再見小時候
    2020-12-21 19:41

    I think you need to do something like this:

    var query = itemList.OrderByDescending(p => p.DateCreated).ToList();
    
    var results = query.Where(i => i.ItemTags
       .All(it => tagsList.Contains(it.TagName.ToLower())));
    

    Then results should then be a list of matching items.

    PS. Your code shows you fetching itemList as a List from your repository and then sorting by date created. This means the sorting isn't being done in the database. Once you turn something into a List you give up the benefits of deferred execution as you will bring back the entire collection into memory.

    EDIT: Here's the test code to prove it works in Linq to Objects:

    public class Item
    {
        public int ItemId { get; set; }
        public string ItemName { get; set; }
        public List ItemTags { get; set; }
        public DateTime DateCreated { get; set; }
    }
    
    public class Tag
    {
        public int TagId { get; set; }
        public string TagName { get; set; }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            RunTags();
        }
    
        private static void RunTags()
        {
            Item i1 = new Item()
            {
                ItemId = 1,
                ItemName = "Item1",
                ItemTags = new List() { new Tag { TagId = 1, TagName = "2008" }, new Tag { TagId = 2, TagName = "Donkey" } }
            };
    
            Item i2 = new Item()
            {
                ItemId = 2,
                ItemName = "Item2",
                ItemTags = new List() { new Tag { TagId = 4, TagName = "Cat" }, new Tag { TagId = 2, TagName = "Donkey" }, new Tag { TagId = 3, TagName = "Seattle" } }
            };
    
            Item i3 = new Item()
            {
                ItemId = 3,
                ItemName = "Item3",
                ItemTags = new List() { new Tag { TagId = 523, TagName = "Manchester united" }, new Tag { TagId = 10, TagName = "European Cup" }, new Tag { TagId = 1, TagName = "2008" } }
            };
    
            Item i4 = new Item()
            {
                ItemId = 4,
                ItemName = "Item4",
                ItemTags = new List() { new Tag { TagId = 05, TagName = "Banana" }, new Tag { TagId = 140, TagName = "Foo" }, new Tag { TagId = 4, TagName = "Cat" } }
            };
    
            Item i5 = new Item()
            {
                ItemId = 5,
                ItemName = "Item5",
                ItemTags = new List() { new Tag { TagId = 05, TagName = "Banana" }, new Tag { TagId = 140, TagName = "Foo" } }
            };
    
            List itemList = new List() { i1, i2, i3, i4, i5 };
    
            string tags = "Manchester United,European Cup,2008";
            List tagsList = tags.Trim().ToLower()
                .Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                .Distinct(StringComparer.CurrentCultureIgnoreCase)
                .ToList();
    
            var query = itemList
                .OrderByDescending(p => p.DateCreated).ToList();
    
    
            var results = query.Where(i => i.ItemTags.All(it => tagsList.Contains(it.TagName.ToLower())));
    
            foreach (var item in results)
            {
                Console.WriteLine(item.ItemName); // Should return "Item3"
            }
    
            Console.ReadLine();
        }
    

    If you want to match any of the tags in the Item's ItemTag list then just change All to Any i.e.

    var results = query.Where(i => i.ItemTags.Any(it => tagsList.Contains(it.TagName.ToLower())));
    

提交回复
热议问题