Tuesday, May 24, 2011

Combining LINQ Query Results

Problems: I had 2 problems when trying to combine the results of 2 separate LINQ queries recently.

1. A compile error with the anonymous classes I created to enable the concat: "The type arguments for method 'System.Linq.Enumerable.Count (System.Collections.Generic.IEnumerable)' cannot be inferred from the usage. Try specifying the type arguments explicitly."

2. A runtime error when trying to concat the two lists even though they apparently have the same columns/properties: "All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists."

Some sample code before:

var combinedDetailsList = (from membershipSold in membershipsSold
select new
{
SalespersonID = membershipSold.MembershipSalespersonID,
SalespersonName = membershipSold.MembershipSalesperson,
MembershipGross = membershipSold.GrossValue,
UpgradeGross = 0.00
})
.Concat
(from upgradeSold in upgradesSold
select new
{
SalespersonID = upgradeSold.MembershipSalespersonID,
SalespersonName = upgradeSold.MembershipSalesperson,
MembershipGross = 0.00,
UpgradeGross = upgradeSold.GrossAdjustment
});


Solutions:

1. To deal with the incompatible type issue you simply cast the values in your anonymous class to a consistent type (easy).

2. The concat problem is described in the following link, with the most useful post being the last one: http://stackoverflow.com/questions/2021861/all-queries-combined-using-a-union-intersect-or-except-operator-must-have-an-equ
Essentially the solution is to either use "let" statements (which I went for) or to convert each to separate lists and then combine them. The use of "lets" is meant to be a bit more effecient (though I think makes it a bit harder to understand what is going on).

Final code which compiles and runs:

var combinedDetailsList = (from membershipSold in membershipsSold
let defaultUpgradeGross = (Decimal?)0.00
select new
{
SalespersonID = (int?)membershipSold.MembershipSalespersonID,
SalespersonName = membershipSold.MembershipSalesperson,
MembershipGross = (Decimal?)membershipSold.GrossValue,
UpgradeGross = defaultUpgradeGross
})
.Concat
(from upgradeSold in upgradesSold
let defaultMembershipGross = (Decimal?)0.00
select new
{
SalespersonID = (int?)upgradeSold.MembershipSalespersonID,
SalespersonName = upgradeSold.MembershipSalesperson,
MembershipGross = defaultMembershipGross,
UpgradeGross = (Decimal?)upgradeSold.GrossAdjustment
});



No comments:

Post a Comment