简体   繁体   中英

LINQ select items in a list that are all in a list of another type

I have a many to many relation created using Entity Framework.

public class Animal
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int AnimalID { get; set; }
    [MaxLength(50)]
    public string AnimalName { get; set; }

    public virtual ICollection<Food> FoodList { get; set; }

}


public class Den
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int DenID { get; set; }
    [MaxLength(50)]
    public string DenName { get; set; }

    public virtual ICollection<Food> FoodList { get; set; }
}

Both Animal and Den contain virtual lists of type food.

public class Food
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int FoodID { get; set; }
    [MaxLength(50)]
    public string FoodName { get; set; }
    public virtual ICollection<Animal> AnimalList { get; set; }
    public virtual ICollection<Den> DenList { get; set; }
}

I have a method which passes in a DenID and I need to return a list of animals that have ALL the foods in their Animal.FoodList that the Den has in it's Den.FoodList.

example if the Den.FoodList contains Meat and Veg then I want a list of Animals that have Meat and Veg in their foodList.

Edit

I have attempted a few things so far.

First of all I have this in my ViewModel

        denFoodList = new List<Food>();

        //Check if myDen requires any Food.
        denFoodList  = MyDen.FoodList.ToList();

I tried looping through each member of the DenFoodList and adding Animals to an Animal list and then gathering that any animal in the list x number of times (where x is the FoodList.Count() ) was the animals I needed, however this method was slow and messy.

I tried using the All method with the animals list and the DenList but I couldn't get it to work.

animalList = context.Animals.Where(a => a.FoodList.All(f => f.DenList));

I've been looking into using Joins and intersects but I have not been successful in using them to solve this problem yet.

End of Edit

Any help is appreciated. Thanks.

Untested:

class Test
{
    private static IEnumerable<Den> Dens()
    {
        var dens = new List<Den>
        {
            new Den
            {
                DenID = 1,
                DenName = "GamePark",
                FoodList = new Collection<Food>()
                {
                    new Food
                    {
                        FoodID = 1,
                        FoodName = "Veg",
                        AnimalList = new Collection<Animal>
                        {
                            new Animal
                            {
                                AnimalID = 234,
                                AnimalName = "Zebra",
                                FoodList = new Collection<Food>{new Food {FoodID = 1, FoodName = "Veg"} }
                            },
                            new Animal
                            {
                                AnimalID = 125,
                                AnimalName = "Buffalo",
                                FoodList = new Collection<Food>{new Food {FoodID = 1, FoodName = "Veg"} }
                            }
                        }
                    },
                    new Food
                    {
                        FoodID = 2,
                        FoodName = "Meat",
                        AnimalList = new Collection<Animal>
                        {
                            new Animal
                            {
                                AnimalID = 003,
                                AnimalName = "Leopard",
                                FoodList = new Collection<Food>{new Food {FoodID = 2, FoodName = "Meat"} }
                            },
                            new Animal
                            {
                                AnimalID = 001,
                                AnimalName = "Lion",
                                FoodList = new Collection<Food>{new Food {FoodID = 2, FoodName = "Meat"} }
                            }
                        }
                    }
                }
            }
        };

        return dens;
    }

    public static IEnumerable<Animal> GetAnimalsWithFoodsInDen(int denId)
    {

        var den = Dens().FirstOrDefault(x => x.DenID == denId);
        var animals = new List<Animal>();
        if (den != null)
        {
            var foods = den.FoodList;
            if (foods != null)
            {
                animals = foods.ToList().Aggregate(animals, (current, food) => current.Union(food.AnimalList).ToList());
            }
        }

        return animals;
    }

    static void Main(string[] args)
    {
        var result = GetAnimalsWithFoodsInDen(1);

        foreach (var a in result)
        {
            Console.WriteLine(a.AnimalName);
        }

        Console.ReadLine();

    }
}

Let's try this

class MyContext : DbContext {}

// ...
using (MyContext context = new MyContext())
{
   var den = context.Den.Find(DenId);
   // Inner join Linq
   var foodList = from a in context.Animals
                  from b in a.FoodList
                  join c in d.FoodList on c.FoodId equals b.FoodId
                  select c;
}

First get the list of food, then get the animals:

Den d = SomeDen();
var food = d.FoodList;
var animals = new List<Animal>();
foreach(var f in food) foreach(var a in f.AnimalList) if(!animals.Contains(a)) animals.Add(a);

Maybe you'd like a dictionary instead of List for performance, depending on your data.

Or perhaps you're looking for something like this?

Dan d = SomeDen();
var food = d.FoodList;
var animals = from a in DB.Animals
              where a.FoodList.Any((f)=>food.Contains(f))
              select a;

The latter should be your intuitive idea, but it's going to be quite slow.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM