Reputation: 185
I am trying to join two object list and update the property(Revenue) in the first object (ProductReport) to be the same the one of the properties(Revenue) in the joined object (Transaction). The code is as blow:
using System.Collections.Generic;
using System.Linq;
namespace TestConsole
{
public class ProductReport
{
public string productName { get; set; }
public int PrdouctID { get; set; }
public double Revenue { get; set; }
}
public class Transaction
{
public double Revenue { get; set; }
public int PrdouctID { get; set; }
}
public class Program
{
static void Main(string[] args)
{
List<ProductReport> products = new List<ProductReport>();
ProductReport p = new ProductReport();
p.productName = "Sport Shoe";
p.PrdouctID = 1;
products.Add(p);
List<Transaction> transactions = new List<Transaction>();
Transaction t1 = new Transaction();
t1.PrdouctID = 1;
t1.Revenue = 100.0;
Transaction t2 = new Transaction();
t2.PrdouctID = 1;
t2.Revenue = 200.00;
transactions.Add(t1);
transactions.Add(t2);
var results = (from product in products
join transaction in transactions on product.PrdouctID equals transaction.PrdouctID into temp
from tran in temp.DefaultIfEmpty()
select new { product, tran }
).ToList();
results.ForEach(x => x.product.Revenue = x.tran.Revenue);
}
}
}
The code joins 2 object lists based on ProductID. I am expecting to see two ProductReport items in the results object with 100.00 and 200.00 revenue respectively. However, the foreach function somehow overwrite the revenue property in the first ProductReport. In the end, both ProductReport have 200.00 as the revenue. Can anyone help me with that and how to easily get the result i want ? Thanks.
Upvotes: 2
Views: 71
Reputation: 141444
The foreach function somehow overwrite the revenue property in the first ProductReport. In the end, both ProductReport have 200.00 as the revenue.
In the following line x.product
refers to the same instance.
results.ForEach(x => x.product.Revenue = x.tran.Revenue);
You have only one ProductReport object, and it can have only one value for its Revenue property. The Revenue property of this single instance cannot simultaneously be both 100.00 and 200.00. The first time you write to it, you set it to 100.00
, the second time you write to it, you overwrite it to 200.00
.
I am expecting to see two ProductReport items in the results object.
Your code creates only one ProductReport
item. If you want to see two (or more) of them, then you need to create two (or more) objects. The following code leverages Select
to do that for you. Whereas your ForEach
mutates the original object, Select
and the rest of the LINQ create a new object and do not mutate the original one.
var results =
from product in products
join transaction in transactions on product.PrdouctID equals transaction.PrdouctID
select new
{
product, transaction
};
var updated = results.Select(x => {
x.product.Revenue = x.transaction.Revenue;
return x.product;
});
And here it is as a Fiddle with this output:
Sport Shoe 100
Sport Shoe 200
Upvotes: 1
Reputation: 473
You'll just need to change your join around
var results = (from p in products
join t in transactions on p.ProductID equals t.ProductId
select new ProductReport{
ProductName = p.productName,
ProductId = p.ProductID,
Revenue = t.Revenue
}).ToList();
You'll then have a list which has 2 entries for ProductId = 1 (Sport Shoe)
ProductName = "Sport Shoe"
ProductId = 1
Revenue = 200.00
ProductName = "Sport Shoe"
ProductId = 1
Revenue = 100.00
Upvotes: 2