Reputation: 121
I have two tables.
Order:
Product:
I want to get the list of all product with earliest delivery date.
I am getting correct data by using following sql. This gives me list of all products with earliest delivery date.
SELECT
p.Name, p.Description, min(o.DeliveryDate)
FROM Product p
JOIN Order o
On o.ProductID = p.ID
Group By p.ID;
I have tried to write it using Linq but something is missing. I am not able to identify how can I write this query.
I have tried out relative stack overflow solutions but not helped in my case.
My Linq is :
await (from p in dbContext.Product
join o in dbContext.Order
on o.ProductID equals p.ID
select new
{
p.ID,
p.Name,
p.Description,
o.DeliveryDate
}).GroupBy(g => g.ID).ToListAsync();
It gives me data after join and group by. Where should I put Min in the Linq to get the Earliest DeliveryDate for the Product?
Upvotes: 0
Views: 2138
Reputation: 271
If you're trying to order your groups you can use the "OrderBy" linq method.
Apply the following after the .GroupBy()
.OrderBy(group => group.First().DeliveryDate).ToListAsync();
Upvotes: 0
Reputation: 25601
I used some classes to stand in for the database, but does this work?
class Product
{
public int ID;
public string Name;
public string Description;
}
class Order
{
public int ProductID;
public DateTime DeliveryDate;
}
class Program
{
static void Main(string[] args)
{
Product[] proTestData = new Product[]
{
new Product() {ID=1, Name="Widget", Description="Banded bulbous snarfblat"},
new Product() {ID=2, Name="Gadget", Description="Hitchhiker's guide to the galaxy"}
};
Order[] ordTestData = new Order[]
{
new Order() {ProductID=1, DeliveryDate=new DateTime(2017,12,14)},
new Order() {ProductID=1, DeliveryDate=new DateTime(2017,12,20)},
new Order() {ProductID=2, DeliveryDate=new DateTime(2017,12,23)},
new Order() {ProductID=2, DeliveryDate=new DateTime(2017,12,22)},
new Order() {ProductID=2, DeliveryDate=new DateTime(2017,12,21)},
new Order() {ProductID=1, DeliveryDate=new DateTime(2017,12,18)}
};
var rows =
(from p in proTestData
join o in ordTestData
on p.ID equals o.ProductID
group o.DeliveryDate by p into grp
select new {
grp.Key.ID,
grp.Key.Name,
grp.Key.Description,
minDate = grp.Min()}
).ToList();
foreach (var row in rows)
{
Console.WriteLine("{0}: {1}", row.Name, row.minDate);
}
}
}
The output is
Widget: 12/14/2017 12:00:00 AM
Gadget: 12/21/2017 12:00:00 AM
Upvotes: 1
Reputation: 109079
I assume you have a navigation property Product.Orders
. If not, it's highly recommended to add it to your code. Having that property, this will achieve what you want:
from p in dbContext.Product
select new
{
p.ID,
p.Name,
p.Description,
MinDeliveryDate = (DateTime?)o.Orders.Min(o => o.DeliveryDate)
}
The cast to DateTime?
is to prevent exceptions when products don't have orders.
If for some reason you don't have the navigation property and really can't add it at the moment you can use:
from p in dbContext.Product
select new
{
p.ID,
p.Name,
p.Description,
MinDeliveryDate = (DateTime?)dbContext.Order
.Where(o => o.ProductID == p.ID)
.Min(o => o.DeliveryDate)
}
Note that by starting the query at Product
and not joining with Order
you don't need the grouping any more.
Upvotes: 1