问题
Im using Linq - objects and I need to do an update. I've been looked around for a while but not really found anything that matches.
So for arguments sake I have 2 simple List's, both with a key so I can use join happily.
I cant find a simple way to update results from obj2 into obj1.
for simple updates I'm currently doing this:
string newValue = "something";
var items = obj1.Where(w => w.ID == iKey).Select(c => {c.<property> = newValue; return c; }).ToArray();
And that all works well and dandy. However if I add into the mix my second table and I want to replace newValue with obj2. then I get problems.
Primarily because I then switch to a full linq statement like:
var UPDATE = from o1 in obj1
join o2 in obj2 on o1.key equals o2.key
select ....;
Its here im getting stuck.
If anybody could help I would be extremly grateful! Thanks in advance.
回答1:
What you're trying to do here isn't a particularly good thing to do with Linq as Linq is meant to be for querying data and not updating it. Your Select
statement is relying on side-effects to perform the update. This generally should be avoided.
However, you can still do what you want.
To start with, I re-arranged your query as:
var items =
obj1
.Where(w => w.Key == iKey)
.Select(c => { c.Value = newValue; return c; })
.ToArray();
Then I refactored it as such:
Func<Obj, string, Obj> update =
(c, v) => { c.Value = v; return c; };
var items = (from w in obj1
where w.Key == iKey
select update(w, newValue)).ToArray();
This still has the side-effect, but I made it more explicit (and hopefully more readable).
Given this refactoring, the UPDATE
query involving the two lists becomes:
var UPDATE = (from o1 in obj1
join o2 in obj2 on o1.Key equals o2.Key
select update(o1, o2.Value)).ToArray();
If you wanted to do this without side-effects, I would suggest the following:
var items = from w in obj1
where w.Key == iKey
select (Action)(() => w.Value = newValue);
Array.ForEach(items.ToArray(), a => a());
var UPDATE = from o1 in obj1
join o2 in obj2 on o1.Key equals o2.Key
select (Action)(() => o1.Value = o2.Value);
Array.ForEach(UPDATE.ToArray(), a => a());
You might not like this syntax, so you could easily write quick extension method on IEnumerable<Action>
to invoke the actions and would make the code look like this:
(from w in obj1
where w.Key == iKey
select (Action)(() => w.Value = newValue)).Invoke();
(from o1 in obj1
join o2 in obj2 on o1.Key equals o2.Key
select (Action)(() => o1.Value = o2.Value)).Invoke();
I hope this helps.
来源:https://stackoverflow.com/questions/3658028/linq-to-objects-update