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.