I want to retrieve a list of Orders based on a multiple Location lists.
For context: a Group can have a multiple Locations (one-to-many) and an Order has one Location (many-to-one). I want to get all the Orders of a Group based on the Locations it has.
The following works for the first element in the list of Groups:
List<Order> orders = _context.Orders
.Where(o => groups.ElementAt(0).Locations.Contains(o.Location))
.ToList()
I want to change it such that it will not only check the first Group element, but all of them. Help is appreciated.
As groups is only a variable, you can use SelectMany to flatten the nested hierarchy before running the query:
var locations = groups.SelectMany(x => x.Locations).ToArray();
This basically changes a nested hierarchy
G1
L11
L12
G2
L21
L22
to a flat list of locations:
L11
L12
L21
L22
After that, you can use the locations in the query:
List<Order> orders = _context.Orders
.Where(o => locations.Contains(o.Location))
.ToList()
If the groups can contain duplicate locations, you could also add a Distinct after the SelectMany.
Is this what you are looking for?
var result = orders
.Where(o => groups.All(f =>
f.Locations.Contains(o.Location))).ToList();
Related
I have a collection and I need to order it by descending date(DateProcessed field) using Linq, first I am grouping by two possible Keys: Booked or Empty. But the data it's not being ordered..
This is my expression:
IEnumerable<IGrouping<string, MyClassMongo>> sub = Model.MyCollection.GroupBy(f => f.IsBooked ? "Booked" : "Empty").OrderByDescending(f => f.FirstOrDefault().DateProcessed);
I'm confused because I am grouping first, I know that after grouping the collection is splitted in two(Booked and Empty) so I am not sure how to handle the sorting because I am grouping first
If you are querying in-memory collection, then just place ordering before grouping:
IEnumerable<IGrouping<string, MyClassMongo>> sub =
Model.MyCollection
.OrderByDescending(f => f.DateProcessed)
.GroupBy(f => f.IsBooked ? "Booked" : "Empty");
Items within each group will be sorted by DateProcessed.
if you want to first Group by and then sort the results within the Group. you can try some thing like below
Model.MyCollection
.GroupBy(f => f.IsBooked,
(f, g) => new{Key=f.DateProcessed, Group = g.OrderByDescending(c=>c.IsBooked)})
.OrderByDescending(f => f.Key);
PS: Code may have syntax issue not tested but the idea should be to create the key withing each group so we can order by
I have a List of ints that model.SelectedIngredients and in this example the list contains the values [15128, 4593,15046,]. I use this list then as a filter in my Linq query as follows:
List<INGREDIENT> selectedIngredients = db.INGREDIENT.Where(i => model.SelectedIngredients.Contains(i.IngredientId)).ToList();
However, this sorts the results by IngredientId ascending as default[4593,15046,15128].
What I would like is to get the selectedIngredients back in the same order as they are in model.SelectedIngredients.
I know I could do it in a for loop but I just wondered if there was a way I could do it within the Linq query?
Thanks
You can acomplish this quite easy by using the index of your list with ids.
List<INGREDIENT> selectedIngredients = db.INGREDIENT
.Where(i => model.SelectedIngredients.Contains(i.IngredientId))
.AsEnumerable()
.OrderBy(i => model.SelectedIngredients.IndexOf(i.IngredientId))
.ToList();
List<INGREDIENT> selectedIngredients = db.INGREDIENT
.Where(i => model.SelectedIngredients.Contains(i.IngredientId))
.orderBy(p=>p.Id).ToList();
This is the default one. Determine in the first place by which it is sorted and then order by it.
I'm trying to get a list of products that match a certain category id. The problem I'm having is that I'm using the select clause before the where, essentially trying to filter once I've already got all the results. Usually its straight forward but since this navigation property is a HashSet its proving more tricky. My repo.GetAll() gets all the products from my database. CategoryProducts is a linking table between products and Categories, its also a navigation property on the product table
ProductRepository repo = new ProductRepository();
var products =
repo.GetAll()
.Select(c => c.CategoryProducts
.Where(p => p.CategoryId == 35));
The above just returns all my products, any help is appreciated.
Your query returns an enumerable that corresponds to all your products, each item of that enumerable is an enumerable itself, containing zero or more categories with ID of 35.
You can change your query to get only products that have category 35 in them:
var products = repo
.GetAll()
.Where(p => p.CategoryProducts.Any(c => c.CategoryId == 35));
I have a LINQ query against an XML, that gives me a list of nested lists, each sublist being a list of an elements("row") attributes.
var items = loadbodies.Descendants("row").Select(a => a.Attributes().Select(b => b.Value).ToList()).ToList();
This works as intended but, what I actually need to is query this against another list of values so as not to have sublists added where one of the elements attributes("messageID") is on the second list. I can do this for one value but need to check it against the entire second list.
The query to exclude a single sublist by a single hardcoded value from the second list is below.
var items = loadbodies.Descendants("row").Where(c => (string)c.Attribute("messageID") != "avaluefromthesecondlist").Select(a => a.Attributes().Select(b => b.Value).ToList()).ToList();
Any help would be much appreciated.
Just use Contains. Note that splitting lines helps readability considerably:
var ids = ...; // Some sequence of ids, e.g. a List<string> or HashSet<string>
var items = loadbodies
.Descendants("row")
.Where(row => ids.Contains((string) row.Attribute("messageId")))
.Select(a => a.Attributes()
.Select(b => b.Value)
.ToList())
.ToList();
Note that you could use a Join call too... but so long as you've got relatively few IDs, this should be fine.
How to use Linq to select and group complex child object from a parents list.
I have an OrderList each of order object has a OrderProductVariantList(OrderLineList), and each of OrderProductVariant object has ProductVariant, and then the ProductVariant object will have a Product object which contains product information.
My goal is to select and group the most popular products from the order list.
Can anyone help me with this?
Many thanks.
Your description is hard to follow, but I think you just want to get out the Products and rank them by the number of times they occur. SelectMany will be helpful for this.
var query = orderList.SelectMany( o => o.OrderLineList )
// results in IEnumerable<OrderProductVariant>
.Select( opv => opv.ProductVariant )
.Select( pv => p.Product )
.GroupBy( p => p )
.Select( g => new {
Product = g.Key,
Count = g.Count()
});
A query is not a result. To view the result you can iterate over the query object:
foreach (var result in query) {
Console.WriteLine(result);
}
As to why query wasn't available in the watch window, I can only imagine that it either wasn't in scope yet, or it had already gone out of scope. Try putting a breakpoint on the line immediately after the line you posted where you assign to query.