score:6

Accepted answer

well for one thing you can speed things up using joins, and only evaluating the valid "target" currencies once:

var targetrates = amdw.fxrates
                      .where(rate => rate.basecurrency == tocurrency)
                      .tolist();

var query = from holding in holdings
            join fxrateholding in amdw.fxrates
              on new { holding.currency, holding.date } equals
                 new { currency = fxrateholding.basecurrency, 
                       date = fxrateholding.valuedate }
            join fxratetocur in targetrates
              on holding.date equals fxratetocur.valuedate
            select new { holding, fxrateholding, fxratetocur };

personally i wouldn't try to update the list in place and i wouldn't mutate the existing holdings (as you currently do in your select call). mutating existing values tends to make your code harder to reason about - which is why linq is designed to be used in a more functional way.

score:0

well you could do it in sql, just note that not everyone will expect side affects in linq, but after all c# is not a functional language.

here is what you could do:

  • for updating a single property just do:

    from a in ab select a.prop = newval;

  • for updating multiple properties, you have the following options:

    1. split the updates in multiple linq queries, each updating a single property (obviously not the best idea)

    2. do the following from a in ab select new { x = a.prop = newval, y = a.prop2 = newval2 };

    3. in a linq method chain (but not in a query expression) you could do ab.select( a=> { x = a.prop = newval; y = a.prop2 = newval2; return x; };

      (actually in linq to objects update there is a suggestion to refactor this last method into an extension method, which will allow it to use in a query expression, as well as clarify the intention).

score:2

you shouldn't use linq when updating objects. linq is supposed to be side-effect free, you should use it to get the items you want to change then do a foreach on them.

foreach(var dhi in query)
{
    decimal factor = dhi.fxratetocur.value / dhi.fxrateholding.value;
    dhi.holding.marketvalue *= factor;
    dhi.holding.fee *= factor;
    dhi.holding.remuneration *= factor;
}

you could also use foreach function defined on list<t> like this.

query.tolist().foreach(dhi =>
        {
            decimal factor = dhi.fxratetocur.value / dhi.fxrateholding.value;
            dhi.holding.marketvalue *= factor;
            dhi.holding.fee *= factor;
            dhi.holding.remuneration *= factor; 
        });

like jeff mercado pointed out in comments, it's not a good idea to make a list just to call foreach() on it.


Related Query

More Query from same tag