Reputation: 13
I have this kind of relationship in my database :
Order => historyStatus => Status
Order
contains a list of HistoryStatus
and HistoryStatus
contains one Status
.
My use case is: search all Order
with a determined Status
and get the latest HistoryStatus
(based on date)
How can I do that in linq to entities and IQueryable
?
Here are the entities :
public class Order
{
public int ID { get; set; }
public virtual ICollection<HistoryStatusOrder> HistoriesStatusOrder { get; set; }
}
public class HistoryStatusOrder
{
public int ID { get; set; }
public DateTime Date { get; set; }
public string StatusOrderCode { get;
public int OrderId { get; set; }
public virtual StatusOrder StatusOrder { get; set; }
public virtual Order Order { get; set; }
}
public class StatusOrder : IEntityBase<string>
{
public string ID { get; set; }
public virtual ICollection<HistoryStatusOrder> HistoriesStatusOrder { get; set; }
}
Here is my Search
method:
// do multiple searches
if (searchOrderVM.OrderNumber != null)
queryable = queryable.Where(x => x.OrderNumber.ToString().Contains(searchOrderVM.OrderNumber.ToString()));
// Next
if (searchOrderVM.SelectedOrdersStatus != null)
{
// Need to return queryable = ....
}
// Next search...
....
// Finally I do .ToList() to launch the query in database.
Thanks for your help :)
Upvotes: 0
Views: 805
Reputation: 1834
This would find all Orders
where the latest HistoryStatusOrder
for that Order
had a particular StatusOrderCode
:
var results = orders.Where (o => o.HistoriesStatusOrder
.OrderByDescending (hso => hso.Date)
.First().StatusOrderCode == "foobar");
(Assuming that each Order
always had at least one HistoryStatusOrder
)
You can write this query in a different way to preserve the IQueryable<Order>
:
var results = orders
.Select (o => new {
Order = o,
LatestHistoryStatusOrder = o.HistoriesStatusOrder
.OrderByDescending (hso => hso.Date)
.First()
})
.Where (x => x.LatestHistoryStatusOrder.StatusOrderCode == "foobar")
.Select (x => x.Order);
foreach(var order in results)
{
// Here you can access:
// order.ID
}
If you want to keep access to the LatestHistoryStatusOrder
, you can skip the last .Select(x => x.Order)
statement:
var results = orders
.Select (o => new {
Order = o,
LatestHistoryStatusOrder = o.HistoriesStatusOrder
.OrderByDescending (hso => hso.Date)
.First()
})
.Where (x => x.LatestHistoryStatusOrder.StatusOrderCode == "foobar");
foreach(var item in results)
{
// Here you can access:
// item.Order.ID
// item.LatestHistoryStatusOrder
}
Upvotes: 2