[ACCEPTED]-LINQ In Line Property Update During Join-linq
Add an update method to your ClassA
class ClassA {
public ClassA UpdateWithB(ClassB objectB) {
// Do the update
return this;
}
}
then 1 use
return from objectA in GetObjectAs()
join objectB in GetObjectBs()
on objectA.Id equals objectB.AId
// update object A with object B data before selecting it
select objectA.UpdateWithB(objectB);
EDIT:
Or use a local lambda function like:
Func<ClassA, ClassB, ClassA> f = ((a,b)=> { a.DoSomethingWithB(b); return a;});
return from objectA in GetObjectAs()
join objectB in GetObjectBs()
on objectA.Id equals objectB.AId
select f(objectA , objectA );
From the word "tables", it sounds 8 like you are getting this data from a database. In 7 which case; no: you can't do this. The closest 6 you can do would to select the objects and 5 the extra columns, and update the properties 4 afterwards:
var qry = from objectA in GetObjectAs()
join objectB in GetObjectBs()
on objectA.Id equals objectB.AId
select new { A = objectA,
objectB.SomeProp, objectB.SomeOtherProp };
foreach(var item in qry) {
item.A.SomeProp = item.SomeProp;
item.A.SomeOtherProp = item.SomeOtherProp;
// perhaps "yield return item.A;" here
}
If you were doing LINQ-to-Objects, there 3 are perhaps some hacky ways you could do 2 it with fluent APIs - not pretty, though. (edit 1 - like this other reply)
I am doing a left join here so I still have 11 all the data from objectA even if the corresponding 10 property in objectB is null. So if the corresponding 9 property in objectB is null then you have 8 to define what to do in objectA. I use this 7 statement all the time for joining two sets 6 of data. You do not need to exhaustively 5 list all properties in objectA and how they 4 map, you only need to list the values you 3 want to update with objectB. Pre-existing 2 values in objectA are safe unless a mapping 1 to objectB is defined.
return from objectA in GetObjectAs()
join objectB in GetObjectBs()
on objectA.Id equals objectB.AId into combinedObj
from subObject in combinedObj.DefaultIfEmpty()
// update object A with object B data before selecting it
select ((Func<objectAType>)(() =>
{
objectA.property = ((subObject == null) ? "Object B was null" : subObject.property);
objectA.property = ((subObject == null) ? "Object B was null" : subObject.property);
return objectA;
}))()
First extend Linq to have an Each option 29 by creating a class called LinqExtensions.
public static class LinqExtensions
{
public static void Each<T>(this IEnumerable<T> source, Action<T> method)
{
foreach (var item in source)
{
method(item);
}
}
}
Then 28 you can use Join to return a list of new 27 objects that contain the original objects 26 with it's appropriate value. The Each will 25 iterate over them allowing you to either 24 assign or pass the values as parameters 23 to each object.
Assignment example:
objectA.Join(objectB,a=>a.Id,b=>b.Id,(a,b) => new {a,b.AValueIWant}).Each(o=>o.a.SomeProperty=o.AValueIWant);
Parameter 22 passing example:
objectA.Join(objectB,a=>a.Id,b=>b.Id,(a,b) => new {a,b.AValueIWant}).Each(o=>o.a.SomeMethod(o.AValueIWant));
The nice thing about this 21 is that ObjectA and ObjectB do not have 20 to be the same type. I have done this with 19 a list of objects joined to a Dictionary 18 (like a lookup). Bad thing is it isn't 17 clear what is going on. You would be better 16 to skip the Each extention and write it 15 like this.
foreach(var change in objectA.Join(objectB,a=>a.Id,b=>b.Id,(a,b) => new {a,b.AValueIWant}))
{
change.a.SomeProperty = change.AValueIWant;
change.a.SomeMethod(change.AValueIWant);
}
But for more clarity I would probably 14 do this:
foreach(var update in objectA.Join(objectB,objectA=>objectA.Id,objectB=>objectB.Id,(objectA,objectB) => new {objectA, Value = objectB.AValueIWant}))
{
update.objectA.SomeProperty = update.Value;
}
You will need to return the whole 13 ObjectA in your new object, because it will 12 be readonly and the only reason this works 11 is because the objects in a collection are 10 referenced allowing you to make your changes 9 to properties on the objects.
But in the 8 end it would be clearest to skip the LINQ 7 join all together and just loop through 6 the collections and look for matches, this 5 will help with future maintenence. LINQ 4 is awesome but just like when you have a 3 hammer it doesn't make everything a nail, when 2 you have a collection it doesn't mean LINQ 1 is the answer.
can u try the let statement? (not at my 1 dev machine to test this out myself):
return from objectA in GetObjectAs()
join objectB in GetObjectBs()
on objectA.Id equals objectB.AId
let objectA.SomeProperty = objectB.AValueIWantBadly
select objectA;
you can try by following..
var list1 = new List<ItemOne>
{
new ItemOne {IDItem = 1, OneProperty = "1"},
new ItemOne {IDItem = 2, OneProperty = null},
new ItemOne {IDItem = 3, OneProperty = "3"},
new ItemOne {IDItem = 4, OneProperty = "4"}
};
var list2 = new List<ItemTwo>
{
new ItemTwo {IDItem = 2, TwoProperty = "2"},
new ItemTwo {IDItem = 3, TwoProperty = "3"},
};
var query = list1.Join(list2, l1 => l1.IDItem, l2 => l2.IDItem, (l1, l2) =>
{
l1.OneProperty = l2.TwoProperty;
return l1;
});
0
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.