简体   繁体   中英

Entity Framework Query - how to return desired results

I have this query

ViewBag.Tags = db.Tag_Group
   .Where(u => 
      u.Tags.Any(d => d.CategoryName.Contains("|" + CategoryID + "|")) 
      & u.Tags.Any(s=>s.Tag_List.Any(d=>d.Item.ItemsOnStock>0)))
   .OrderBy(y => y.TagGrupName)
   .ToList();

It returns all groups and not only ItemsOnStock>0 groups.

What am I doing wrong ?

Tag_List has many Item and many Tags . Tag_Group has many Tags

Table Tag_List is used to store Tags for specific Items .

I only need List<Tag_Group> for items that are on stock. Is there some better way to do this ?

This is a disguised "filtered Include" question and the answer is similar to the usual work-around for lack of filtering in Include .

In your case, you better start the query at the Tags and group them by their TagGroup (of which I assume the navigation property exists):

db.Tags
  .Where(t => t.CategoryName.Contains("|" + CategoryID + "|") 
           && t.Tag_List.Any(d => d.Item.ItemsOnStock > 0))
  .GroupBy(t => t.TagGroup)
  .AsEnumerable()
  .Select(g => g.Key)
  .OrderBy(y => y.TagGroupName)
  .ToList();

Remember to disable lazy loading, so the groups' Tags collections won't be populated fully when you access them.

Could it be that you get the wrong result because of your one & instead of && ?

So you have a class Tag_Group . Every object of Tag_Group has zero or more Tags .

Every Tag has a string CategoryName and an IEnumerable Tag_List that contains zero or more Items . Every Item has an int(?) property ItemOnStock . The int part is not important. It can be any class as long as you can compare it with zero.

It seems you want all Tag_Group objects that have at least one Tag in its sequence of Tags that:

  • Has a CategoryName equal to "|" + CategoryID + "|"
  • AND has at least one item in Tag_List that has an ItemOnStock > 0

Or could it be that you want all Tag_Group objects that

  • Has at least one Tag in Tags with a CategoryName equal to "|" + CategoryID + "|"
  • OR has at least one Tag in Tags that has at leas one item in Tag_List that has an ItemOnStock > 0 . This Tag may be a different Tag than the one with the CategoryName

I assume you want the AND option.

Although you didn't say so, I assume db is your dbContext, and you want your query to be performed by the database, so AsQueryable, and not AsEnumerable.

var CategoryId = ...
string categoryName = "|" + CategoryId + "|";

var result = db.Tag_Group
   // I want only those tagGroupElements that have at least one Tag
   // in sequence Tags that matches both conditions:
   .Where(tagGroupElement => tagGroupEleent.Tags
             // the tagGroupElement should have a matching CategoryName
       .Where(tag => tag.CategoryName == categoryName)
             // and the tagGroupElement should have at least one item
             // in Tag_List with ItemOnStock > 0
          && tag.Tag_List
              .Where(tagListElement => tagListElement.ItemOnStock > 0)
              .Any())
       .Any());

Thank you both for your help :)

I ended up using a bit modified Gert's answer since I needed Tags grouped by TagGroup

db.Tags
  .Where(t => t.CategoryName.Contains("|" + CategoryID + "|") 
           && t.Tag_List.Any(d => d.Item.ItemsOnStock > 0))
  .GroupBy(t => t.TagGroup.GroupName)
  .OrderBy(y => y.Key)
  .ToList();

I learned a lot from your answers

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