views:

31

answers:

1

Hi all.

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.

A: 

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.

Enigmativity
Yes, an Update extension method would make the code read more naturally, as in "items.Where(...).Update(...)"
Felix Ungman
Thankyou for your detailed response. I'll give it ago very shrotly and let you know.
DubMan