I have a following problem with LINQ to Entities. I am selecting records from DB, group them and then order them by Id descending. Then i want to select First item but only if Quantity is != 0. I think because i have to use FirstOrDefault i am getting wrong results but am not sure how to correct it.
DB
Now this query will give me ID's 2 and 1 grouped and 4 "grouped". What i need is to select FIRST items only if Quantity is != 0 and am not sure how to get that.
data = DbContext.Items.Where(x.WarehouseId == 1)
.GroupBy(x => x.ItemCode, (key, g) => g.OrderByDescending(y => y.Id).FirstOrDefault())
.OrderBy(parameters.SortExpression)
.Skip(parameters.Start)
.Take(parameters.Length);
If WarehouseID is 1 i need to get only row with ID 4 back. Any help is appreciated.
Edit: First i need to groupBy ItemCode, then i will have two groups for my case above. That's 1 and 2 for first group, and 4 for second group. Then i order them by Id descending and i get (2, 1), (4). Then i need to select first from group but only if Quantity is != 0. If Quantity is zero i don't want to select anything from a group.
Image to clarify what i need. I'm stuck on last step Take FristFrom each group only if quantity is != 0
EDIT: This is, what you want to do:
var data = DbContext.Items
.Where(p => p.WarehouseId == 1)
.GroupBy(p => p.ItemCode, (key, items) => new { Key = key, Items = items, ItemsCountWithQuantityZero = items.Where(p => p.Quantity == 0).Count() })
.Where(p => p.ItemsCountWithQuantityZero == 0)
.Select(p => p.Items.OrderByDescending(q => q.Id).First());
Related
Let's say you have these two tables:
CARS
ID CAR_MODEL
11 Mustang
22 Camaro
33 F-150
PARTS
ID CAR_ID PART_NAME
1 11 Steering Wheel
2 22 Steering Wheel
3 22 Headlights
You need to create a search form. How would you you make this work:
var query = db.CARS.include(u => u.PARTS);
if(model.CarPartName != "")
query = query.where(u => u.PARTS.PART_NAME == model.CarPartName); //this doesn't work
return query.ToList();
There is currently a foreign key relationship between PARTS.CAR_ID and CARS.ID but for some reason when I attempt u.PARTS. I can't append on a column name.
Any idea how to make this optional join work?
That wouldn't work that way, because a car can have many parts, thus u.PARTS is returning a collection. There are many solutions to this problem, you can start by Cars collection (as you did), or you can start by PARTS collection. If you started with PARTS collection, it would look like:
var query = db.PARTS.Include(p => p.Car);
if(model.CarPartName != "")
query = query.Where(u => u.PART_NAME == model.CarPartName);
return query.Select(p => p.Car).Distinct().ToList();
With Cars:
var query = db.CARS.include(u => u.PARTS);
if(model.CarPartName != "")
query = query.Where(u => u.PARTS.Any( up => up.PART_NAME == model.CarPartName));
return query.ToList();
Note: I added the first one, just because I wanted to show what is going on.
I have a table set up as follows:
Section SectionOrder
Sect1 1
Sect2 2
Sect3 3
Sect3 3
Sect1 1
Sect2 2
I need to pull out distinct sections in correct section order. Here is the linq that I'm using, but it's not putting them in the correct order for some reason.
var myVar = (from x in context.Documents
orderby x.SectionOrder ascending
select x.Section).Distinct();
I then want to be able to loop through myVar and put each item in a list as follows:
foreach (var t in myVar)
{
listOfDocTypeSections.Add(t);
}
The ordering of OrderBy and Distinct matters: while OrderBy produced an ordered sequence, Distinct doesn't. You need to put Distinct first, and then use OrderBy. However, since you take Distinct on one attribute, and order on the other attribute, you need to do it differently:
var myVar = context
.Documents
.GroupBy(x => x => x.Section) // This replaces Distinct()
.OrderBy(g => g.FirstOrDefault().SectionOrder) // There will be no default
.Select(g => g.Key);
This approach replaces Distinct with GroupBy, and orders on the first SectionOrder item of a group. You can change this sorting strategy to sort on some other item within the Section, say, Min or Max value of SectionOrder:
var myVar = context
.Documents
.GroupBy(x => x => x.Section)
.OrderBy(g => g.Max(x => x.SectionOrder))
.Select(g => g.Key);
I have a requirement where I need to filter out the null values from a list, only if the null value appears after the first non-null value and before the last non-null value.
Product one = new Product { Name="A" Priority="1" Value=null };
Product two = new Product { Name="A" Priority="2" Value=null };
Product three = new Product { Name="A" Priority="3" Value="10" };
Product four = new Product { Name="A" Priority="4" Value=null };
Product five = new Product { Name="A" Priority="5" Value="20" };
Product six = new Product { Name="A" Priority="6" Value=null };
In the example, I need to first sort the list of products based on their priority and then check the first non-null value (ie., priority 3) and last non-null value (ie, priority 5), then get the list of all products with null values within priority 3 & 5. So, in our example only Product 4 with Priority 4 is the record I am looking for.
I got to the part of actually grouping them by products and sorting them by priority but stuck on how to proceed after that
from p in Products
group p by p.Product into grp
select new
{
Product = grp.Key
Values = grp.OrderBy(x => x.Priority)
}
Can someone point me as how to proceed? I am thinking I may to use the indexes to identify all the non-null and iterate through to get min and max Priority values and later query for all records with blank null values within the min/max priority.
It would be easier and more efficient if you determined which values are your start and stop points in the group and filter from there.
var query =
from product in Products
group product by product.Name into g
let ordered = g.OrderBy(p => p.Priority).ToList()
let firstIndex = ordered.FindIndex(p => p.Value != null)
let lastIndex = ordered.FindLastIndex(p => p.Value != null)
select new
{
Product = g.Key,
Values = ordered
.Skip(firstIndex + 1)
.Take(lastIndex - firstIndex - 1)
.Where(p => p.Value == null),
};
How about this (you can use .Select instead of .SelectMany to get separate groups for each product. .SelectMany combines all the valid result records into a single list):
Products
.GroupBy(p => p.Name)
.SelectMany (grp =>
grp.OrderBy(p => p.Priority) // sort by priority
.SkipWhile(p => p.Value == null) // skip null entries at beginning
.Reverse() // reverse
.SkipWhile(p => p.Value == null) // skip null entries at end
.Reverse() // reverse back to normal
.Where(p => p.Value == null) // then find null entries
);
Demo: http://ideone.com/2dU9L
How do I return a List, grouped by a property?
In my action, I return a view like so:
return View(context.Lines.Where(x=>x.EnquiryId == id).ToList());
This works fine, but what I need to do is group these Lines by a particular vehicle. In my Lines table, this has a column which stores the vehicle ID that a particular Line is linked too. For example, line 1 and 2, may have a vehicle ID of 1, where as line 3 and 4 may have a vehicle ID of 2.
Do you want to group or just order? Because if your result is a list of items, you'll just want to order them properly.
var result = context.Lines
.Where(x => x.EnquiryId == id)
.OrderBy(x => x.VehicleId)
.ToList();
GroupBy returns a list of lists:
var result = context.Lines
.Where(x => x.EnquiryId == id)
.GroupBy(x => x.VehicleId);
I have a linq expression that returns transactions in groups. Each transaction has a numerical value and I now need to know what is the highest value from all the transactions returned. This value is held in a field called TransactionId
Here is the expression I am using to get the grouped list.
var transactions = ctx.MyTransactions
.Where (x => x.AdapterId == Id)
.GroupBy(x => x.DeviceTypeId);
I now need to write an expression that works on the “transactions” grouped list to find the “max” of the TransactionId field. I’ve tried different ideas but none seem to work with the grouped results. I’m new to linq so I’m not sure how to do this.
Have you tried finding the maximum in each group and then finding the maximum of that over all groups?
int max = transactions.Max(g => g.Max(t => t.TransactionId));
Or you could just query the database again:
int max = ctx.MyTransactions
.Where(x => x.AdapterId == Id)
.Max(t => t.TransactionId);
This will give you the max in each group
var transactionIds = ctx.MyTransactions
.Where (x => x.AdapterId == Id)
.GroupBy(x => x.DeviceTypeId,
g => new {
DeviceTypeId = g.Key,
MaxTransaction = g.Max(x => x.TransactionId)
});