Reputation: 88
I have 2 tables _customerRepository.GetAllQueryable()
and _customerSettlementRepository.GetAllQueryable()
.
In table _customerSettlementRepository.GetAllQueryable()
, I have column ApplyD (date)
, after joining these two together, I want to find out max ApplyD
in the where clause. This is my code:
var settlements = from c in _customerRepository.GetAllQueryable()
join cs in _customerSettlementRepository.GetAllQueryable() on new {c.CustomerMainC, c.CustomerSubC}
equals new {cs.CustomerMainC, cs.CustomerSubC} into c1
where cs.ApplyD == (c1.Select(b=>b.ApplyD).Max())
select new CustomerSettlementViewModel()
{
TaxRate = cs.TaxRate
};
Upvotes: 0
Views: 253
Reputation: 88
This is my syntet error, I need to write this since the first
var settlements = from c in _customerRepository.GetAllQueryable()
join cs in _customerSettlementRepository.GetAllQueryable() on new {c.CustomerMainC, c.CustomerSubC}
equals new {cs.CustomerMainC, cs.CustomerSubC}
select new CustomerSettlementViewModel()
{
TaxRate = cs.TaxRate
};
settlements = settlements.Where(p => p.ApplyD == settlements.Max(b => b.ApplyD));
Upvotes: 0
Reputation: 30502
It's remarkable that quite often in these questions people come up with an SQL(-like) statement without specification of the goal they want to reach. Hence it is impossible to see whether the provided statement fulfills the requirements.
Anyway, it seems you have something like Customers
(in CustomerRepository
) and CustomerSettlements
in CustomerSettlementRepository
.
both Customers
and CustomerSettlements
have a CustomerMainC and a CustomerSubC. You want to join Customers
and CustomerSettlements
on these two properties.
A CustomerSettlement
also has an ApplyD
and a TaxRate
.
You only want to keep the join results where ApplyD
has the maximum value of ApplyD
Finally, from every remaining join result you want to create one CustomerSettlementViewModel
object with the value of the TaxRate in the join result that was taken from the CustomerSettlement
.
Now that I wrote this, it baffles me why you need to join in the first place, because you only use values from the CustomerSettlements, not from the Customer.
Besides, if two Customers are joined with the same CustomerSettlements. this will result in two equal CustomerSettlementViewModel objects.
But let's assume this is really what you want.
In baby steps:
IQueryable<Customer> customers = ...
IQueryable<CustomerSettlement> customerSettlements = ...
var joinResults = customers.Join(customerSettlements
customer => new {customer.CustomerMainC, customer.CustomerSubC},
settlement => new {settlement.CustomerMainC, settlement.CustomerSubC}
(customer, settlement) => new
{
settlement.ApplyD,
settlement.TaxRate,
// add other properties from customers and settlements you want in the end result
});
In words: take all Customers
and all CustomerSettlements
. From every Customer
create an object having the values of the customer's CustomerMainC
and CustomerSubC
. Do the same from every CustomerSettlement
. When these two objects are equal, create a new object, having the values of the CustomerSettlement
's ApplyD
and TaxRate
(and other properties you need in the end result)
Note that this is still an IQueryable. No query is performed yet.
From this joinResult
you only want to keep those objects that have the value of ApplyD that equals the maximum value of ApplyD.
This question on StackOverflow is about selecting the records with the max value. The idea is to group the records into groups with the same value for ApplyD
. Then order the groups in descending Key order and take the first group.
var groupsWithSameApplyD = joinResults.GroupBy(
joinedItem => joinedItem.ApplyD,
joinedItem => new CustomerSettlementViewModel()
{
TaxRate = orderedItem.TaxRate,
// add other values from joinedItems as needed
});
Every group in groupsWithSameApplyD has a key equal to ApplyD. The group consists of CustomerSettlementViewModel objects created frome the joinedItems that all have the same ApplyD that is in the Key
of the group.
Now order by descending:
var orderedGroups = groupsWithSameApplyD.OrderByDescending(group => group.Key);
The first group contains all elements that had the largest ApplyD. Your desired result is the sequence of elements in the group.
If there is no group at all, return an empty sequence. Note if a sequence is requested as result, it is always better to return an empty sequence instead of null, so callers can use the returned value in a foreach without having to check for null return
var result = orderedGroups.FirstOrDefault() ??
// if no groups at all, return empty sequence:
Enumerable.Empty<CustomerSettlementViewModel>();
Note: the FirstOrDefault
is the first step where the query is actually performed. If desired you could put everything in one big query. Not sure if this would improve readability and maintainability.
Upvotes: 2