Problem
The issue lies on this statement:
where tmp.PayAmount != tmp1.DepositAmount //the culprit
And since the tmp1
is defined as a single child transaction, the statement would result in equating wrong values:
Visualizer:
1000 != 600 //(result: true -> selected) comparing parent 1 and child 1
1000 != 400 //(result: true -> selected) comparing parent 1 and child 2
3000 != 1000 //(result: true -> selected) comparing parent 2 and child 3
3000 != 1000 //(result: true -> selected) comparing parent 2 and child 4
3000 != 1000 //(result: true -> selected) comparing parent 2 and child 5
5000 != 2000 //(result: true -> selected) comparing parent 2 and child 5
//However, you do not want it to behave like this actually
But what you want to have is rather:
Visualizer:
1000 != (600 + 400) //(result: false -> not selected) comparing parent 1 and child 1 & 2, based on the TransactionId
3000 != (1000 + 1000 + 1000) //(result: false -> not selected) comparing parent 2 and child 3, 4, & 5, based on the TransactionId
5000 != (2000) //(result: true -> selected) comparing parent 3 and child 6, based on the TransactionId
6000 != nothing paid //(result: true -> selected) comparing parent 3 with the whole childTransaction and found there isn't any payment made
Thus, you should make tmp1
is as a collection of children rather than single child.
Solution
Unpaid Transaction
Change your code like this:
var data = (from tmp in context.ParentTransaction
join tmp1 in context.ChildTransaction.GroupBy(x => x.TransactionId) //group this by transaction id
on tmp.TransactionId equals tmp1.Key //use the key
where tmp.PayAmount > tmp1.Sum(x => x.DepositAmount) //get the sum of the deposited amount
select tmp)
.Union( //added after edit
(from tmp in context.ParentTransaction
where !context.ChildTransaction.Select(x => x.TransactionId).Contains(tmp.TransactionId)
select tmp)
);
Explanations
This line:
join tmp1 in context.ChildTransaction.GroupBy(x => x.TransactionId) //group this by transaction id
Making use of GroupBy
in Linq
, this line makes tmp1
a group of children rather than a single child and, rightfully, based on its foreign key, which is the TransactionId
.
Then this line:
on tmp.TransactionId equals tmp1.Key //use the key
We simply equates tmp.TransactionId
with the children's group key tmp1.Key
Then the next line:
where tmp.PayAmount > tmp1.Sum(x => x.DepositAmount) //get the sum of the deposited amount
Get the sum value of the children's DepositAmount
rather than single child's DepositAmount
which is less than the PayAmount
in the parent, and then
select tmp
Select all the parent transactions which satisfy all the criteria above. This way, we are half-done.
The next step is to consider transaction which occurs in the parent but not in the child(ren). This is considered as unpaid too.
We can combine the result of the first query
with the second query
using Union
.Union( //added after edit
(from tmp in context.ParentTransaction
where !context.ChildTransaction.Select(x => x.TransactionId).Contains(tmp.TransactionId)
select tmp)
);
This selects whatever exist in the parent transaction but doesn't exist at all in the child (and therefore considered unpaid).
And you would get the right data
, consisting of your ParentTransaction
rows which are not fully paid, both for the parent transaction whose TransactionId
exists in the child or not.
Paid Transaction
As for the paid transaction, simply change the query from >
to <=
:
var datapaid = (from tmp in context.ParentTransaction
join tmp1 in context.ChildTransaction.GroupBy(y => y.TransactionId)
on tmp.TransactionId equals tmp1.Key
where tmp.PayAmount <= tmp1.Sum(x => x.DepositAmount)
select tmp);
Combined
We can further simplify the above query like this:
var grp = context.ChildTransaction.GroupBy(y => y.TransactionId);
var data = (from tmp in context.ParentTransaction
join tmp1 in grp //group this by transaction id
on tmp.TransactionId equals tmp1.Key //use the key
where tmp.PayAmount > tmp1.Sum(x => x.DepositAmount)
select tmp)
.Union((
from tmp in context.ParentTransaction
where !context.ChildTransaction.Select(x => x.TransactionId).Contains(tmp.TransactionId)
select tmp));
var datapaid = (from tmp in context.ParentTransaction
join tmp1 in grp
on tmp.TransactionId equals tmp1.Key
where tmp.PayAmount <= tmp1.Sum(x => x.DepositAmount)
select tmp);